import { useMutation, useQueryClient } from '@tanstack/react-query';
import { gql } from 'graphql-request';
import { fetchGraphQL, createQueryKey } from '../client';
import type {
  JournalEntryDraft,
  CreateJournalEntryDraftInput,
  UpdateJournalEntryDraftInput,
} from '@/types/accounting';

// GraphQL Mutations
const CREATE_JOURNAL_ENTRY_DRAFT_MUTATION = gql`
  mutation CreateJournalEntryDraft($input: CreateJournalEntryDraftInput!) {
    createJournalEntryDraft(input: $input) {
      id
      companyId
      name
      voucherNumber
      status
      createdBy
      createdAt
      updatedAt
    }
  }
`;

const UPDATE_JOURNAL_ENTRY_DRAFT_MUTATION = gql`
  mutation UpdateJournalEntryDraft($input: UpdateJournalEntryDraftInput!) {
    updateJournalEntryDraft(input: $input) {
      id
      companyId
      name
      voucherNumber
      documentDate
      description
      fiscalYearId
      lines {
        lineNumber
        accountId
        debitAmount
        creditAmount
        description
        vatCode
      }
      attachmentIds
      status
      updatedAt
    }
  }
`;

const POST_JOURNAL_ENTRY_DRAFT_MUTATION = gql`
  mutation PostJournalEntryDraft($id: ID!) {
    postJournalEntryDraft(id: $id) {
      id
      companyId
      status
      transactionId
      updatedAt
    }
  }
`;

const DISCARD_JOURNAL_ENTRY_DRAFT_MUTATION = gql`
  mutation DiscardJournalEntryDraft($id: ID!) {
    discardJournalEntryDraft(id: $id) {
      id
      companyId
      status
      updatedAt
    }
  }
`;

// Response types
interface CreateDraftResponse {
  createJournalEntryDraft: JournalEntryDraft;
}

interface UpdateDraftResponse {
  updateJournalEntryDraft: JournalEntryDraft;
}

interface PostDraftResponse {
  postJournalEntryDraft: JournalEntryDraft;
}

interface DiscardDraftResponse {
  discardJournalEntryDraft: JournalEntryDraft;
}

/**
 * Hook to create a new journal entry draft.
 */
export function useCreateJournalEntryDraft() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async (input: CreateJournalEntryDraftInput) => {
      const data = await fetchGraphQL<CreateDraftResponse>(
        CREATE_JOURNAL_ENTRY_DRAFT_MUTATION,
        { input }
      );
      return data.createJournalEntryDraft;
    },
    onSuccess: (data) => {
      // Invalidate drafts list for this company
      queryClient.invalidateQueries({
        queryKey: createQueryKey('journalEntryDrafts', { companyId: data.companyId }),
      });
    },
  });
}

/**
 * Hook to update a journal entry draft (auto-save).
 * Returns the mutation without automatic cache invalidation for better performance.
 */
export function useUpdateJournalEntryDraft() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async (input: UpdateJournalEntryDraftInput) => {
      const data = await fetchGraphQL<UpdateDraftResponse>(
        UPDATE_JOURNAL_ENTRY_DRAFT_MUTATION,
        { input }
      );
      return data.updateJournalEntryDraft;
    },
    onSuccess: (data) => {
      // Update the specific draft in cache
      queryClient.setQueryData(
        createQueryKey('journalEntryDraft', { id: data.id }),
        data
      );
      // Also update it in the list if it exists
      queryClient.setQueriesData<JournalEntryDraft[]>(
        { queryKey: createQueryKey('journalEntryDrafts', { companyId: data.companyId }) },
        (oldData) => {
          if (!oldData) return oldData;
          return oldData.map((draft) => (draft.id === data.id ? data : draft));
        }
      );
    },
  });
}

/**
 * Hook to post a journal entry draft to the ledger.
 */
export function usePostJournalEntryDraft() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async (id: string) => {
      const data = await fetchGraphQL<PostDraftResponse>(
        POST_JOURNAL_ENTRY_DRAFT_MUTATION,
        { id }
      );
      return data.postJournalEntryDraft;
    },
    onSuccess: (data) => {
      // Invalidate drafts list to remove the posted draft
      queryClient.invalidateQueries({
        queryKey: createQueryKey('journalEntryDrafts', { companyId: data.companyId }),
      });
      // Invalidate single draft cache
      queryClient.invalidateQueries({
        queryKey: createQueryKey('journalEntryDraft', { id: data.id }),
      });
      // Invalidate bank transactions as the matched transaction status may have changed
      queryClient.invalidateQueries({
        queryKey: createQueryKey('bankTransactions', { companyId: data.companyId }),
      });
    },
  });
}

/**
 * Hook to discard a journal entry draft.
 */
export function useDiscardJournalEntryDraft() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: async (id: string) => {
      const data = await fetchGraphQL<DiscardDraftResponse>(
        DISCARD_JOURNAL_ENTRY_DRAFT_MUTATION,
        { id }
      );
      return data.discardJournalEntryDraft;
    },
    onSuccess: (data) => {
      // Invalidate drafts list to remove the discarded draft
      queryClient.invalidateQueries({
        queryKey: createQueryKey('journalEntryDrafts', { companyId: data.companyId }),
      });
      // Invalidate single draft cache
      queryClient.invalidateQueries({
        queryKey: createQueryKey('journalEntryDraft', { id: data.id }),
      });
    },
  });
}
