import { mutationOptions } from '@tanstack/react-query';
import { quotationDocumentKeys } from '@/features/crm/quotations/document/queries';
import { getQueryClient } from '@/lib/query-client';
import {
  approveApproval,
  cancelApproval,
  createApprovalWorkflow,
  deleteApprovalWorkflow,
  rejectApproval,
  replaceApprovalWorkflowSteps,
  returnApproval,
  submitApproval,
  submitQuotationForApproval,
  updateApprovalWorkflow
} from './service';
import { approvalKeys, approvalWorkflowKeys } from './queries';
import { quotationKeys } from '@/features/crm/quotations/api/queries';
import type {
  ApprovalActionPayload,
  ApprovalStepMutationPayload,
  ApprovalWorkflowMutationPayload,
  SubmitApprovalPayload
} from './types';

async function invalidateApprovalLists() {
  await getQueryClient().invalidateQueries({ queryKey: approvalKeys.lists() });
}

async function invalidateApprovalDetail(id: string) {
  await getQueryClient().invalidateQueries({ queryKey: approvalKeys.detail(id) });
}

async function invalidateApprovalWorkflows() {
  await getQueryClient().invalidateQueries({ queryKey: approvalWorkflowKeys.lists() });
}

async function invalidateApprovalWorkflowDetail(id: string) {
  await getQueryClient().invalidateQueries({ queryKey: approvalWorkflowKeys.detail(id) });
}

async function invalidateQuotationQueries(quotationId: string) {
  const queryClient = getQueryClient();
  await Promise.all([
    queryClient.invalidateQueries({ queryKey: quotationKeys.lists() }),
    queryClient.invalidateQueries({ queryKey: quotationKeys.detail(quotationId) }),
    queryClient.invalidateQueries({ queryKey: quotationDocumentKeys.data(quotationId) }),
    queryClient.invalidateQueries({ queryKey: quotationDocumentKeys.preview(quotationId) })
  ]);
}

async function invalidateRelatedEntityQueries(approvalId: string) {
  const queryClient = getQueryClient();
  const cachedDetail = queryClient.getQueryData<{ approval: { request: { entityType: string; entityId: string } } }>(
    approvalKeys.detail(approvalId)
  );

  if (cachedDetail?.approval.request.entityType === 'quotation') {
    await invalidateQuotationQueries(cachedDetail.approval.request.entityId);
  }
}

export const submitApprovalMutation = mutationOptions({
  mutationFn: (data: SubmitApprovalPayload) => submitApproval(data),
  onSettled: async (_data, error) => {
    if (!error) {
      await invalidateApprovalLists();
    }
  }
});

export const submitQuotationApprovalMutation = mutationOptions({
  mutationFn: ({ id, remark }: { id: string; remark?: string }) => submitQuotationForApproval(id, remark),
  onSettled: async (_data, error, variables) => {
    if (!error) {
      await Promise.all([invalidateApprovalLists(), invalidateQuotationQueries(variables.id)]);
    }
  }
});

export const cancelApprovalMutation = mutationOptions({
  mutationFn: (id: string) => cancelApproval(id),
  onSettled: async (_data, error, id) => {
    if (!error) {
      await Promise.all([
        invalidateApprovalLists(),
        invalidateApprovalDetail(id),
        invalidateRelatedEntityQueries(id)
      ]);
    }
  }
});

export const approveApprovalMutation = mutationOptions({
  mutationFn: ({ id, values }: { id: string; values: ApprovalActionPayload }) =>
    approveApproval(id, values),
  onSettled: async (_data, error, variables) => {
    if (!error) {
      await Promise.all([
        invalidateApprovalLists(),
        invalidateApprovalDetail(variables.id),
        invalidateRelatedEntityQueries(variables.id)
      ]);
    }
  }
});

export const rejectApprovalMutation = mutationOptions({
  mutationFn: ({ id, values }: { id: string; values: ApprovalActionPayload }) =>
    rejectApproval(id, values),
  onSettled: async (_data, error, variables) => {
    if (!error) {
      await Promise.all([
        invalidateApprovalLists(),
        invalidateApprovalDetail(variables.id),
        invalidateRelatedEntityQueries(variables.id)
      ]);
    }
  }
});

export const returnApprovalMutation = mutationOptions({
  mutationFn: ({ id, values }: { id: string; values: ApprovalActionPayload }) =>
    returnApproval(id, values),
  onSettled: async (_data, error, variables) => {
    if (!error) {
      await Promise.all([
        invalidateApprovalLists(),
        invalidateApprovalDetail(variables.id),
        invalidateRelatedEntityQueries(variables.id)
      ]);
    }
  }
});

export const createApprovalWorkflowMutation = mutationOptions({
  mutationFn: (data: ApprovalWorkflowMutationPayload) => createApprovalWorkflow(data),
  onSettled: async (_data, error) => {
    if (!error) {
      await invalidateApprovalWorkflows();
    }
  }
});

export const updateApprovalWorkflowMutation = mutationOptions({
  mutationFn: ({
    id,
    values
  }: {
    id: string;
    values: Partial<ApprovalWorkflowMutationPayload>;
  }) => updateApprovalWorkflow(id, values),
  onSettled: async (_data, error, variables) => {
    if (!error) {
      await Promise.all([
        invalidateApprovalWorkflows(),
        invalidateApprovalWorkflowDetail(variables.id)
      ]);
    }
  }
});

export const deleteApprovalWorkflowMutation = mutationOptions({
  mutationFn: (id: string) => deleteApprovalWorkflow(id),
  onSettled: async (_data, error, id) => {
    if (!error) {
      const queryClient = getQueryClient();
      await invalidateApprovalWorkflows();
      queryClient.removeQueries({ queryKey: approvalWorkflowKeys.detail(id) });
    }
  }
});

export const replaceApprovalWorkflowStepsMutation = mutationOptions({
  mutationFn: ({
    workflowId,
    steps
  }: {
    workflowId: string;
    steps: ApprovalStepMutationPayload[];
  }) => replaceApprovalWorkflowSteps(workflowId, steps),
  onSettled: async (_data, error, variables) => {
    if (!error) {
      await Promise.all([
        invalidateApprovalWorkflows(),
        invalidateApprovalWorkflowDetail(variables.workflowId)
      ]);
    }
  }
});
