import { mutationOptions } from '@tanstack/react-query';
import { quotationDocumentKeys } from '@/features/crm/quotations/document/queries';
import { quotationKeys } from '@/features/crm/quotations/api/queries';
import { getQueryClient } from '@/lib/query-client';
import {
  activateApprovalWorkflow,
  approveApproval,
  cancelApproval,
  cloneApprovalWorkflow,
  createApprovalWorkflow,
  createApprovalWorkflowStep,
  deactivateApprovalWorkflow,
  deleteApprovalWorkflow,
  deleteApprovalWorkflowStep,
  rejectApproval,
  reorderApprovalWorkflowSteps,
  returnApproval,
  submitApproval,
  submitQuotationForApproval,
  updateApprovalWorkflow,
  updateApprovalWorkflowStep
} from './service';
import { approvalKeys, approvalWorkflowKeys } from './queries';
import type {
  ApprovalActionPayload,
  ApprovalStepMutationPayload,
  ApprovalStepReorderPayload,
  ApprovalStepUpdatePayload,
  ApprovalWorkflowFilters,
  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 invalidateApprovalWorkflowLists(filters?: ApprovalWorkflowFilters) {
  const queryClient = getQueryClient();
  await Promise.all([
    queryClient.invalidateQueries({ queryKey: approvalWorkflowKeys.lists() }),
    ...(filters ? [queryClient.invalidateQueries({ queryKey: approvalWorkflowKeys.list(filters) })] : [])
  ]);
}

async function invalidateApprovalWorkflowDetail(id: string) {
  const queryClient = getQueryClient();
  await Promise.all([
    queryClient.invalidateQueries({ queryKey: approvalWorkflowKeys.detail(id) }),
    queryClient.invalidateQueries({ queryKey: approvalWorkflowKeys.steps(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: (values: SubmitApprovalPayload) => submitApproval(values),
  onSettled: async (_data, error) => {
    if (!error) {
      await invalidateApprovalLists();
    }
  }
});

export const submitQuotationForApprovalMutation = 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 submitQuotationApprovalMutation = submitQuotationForApprovalMutation;

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 invalidateApprovalWorkflowLists();
    }
  }
});

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([
        invalidateApprovalWorkflowLists(),
        invalidateApprovalWorkflowDetail(variables.id)
      ]);
    }
  }
});

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

export const cloneApprovalWorkflowMutation = mutationOptions({
  mutationFn: (id: string) => cloneApprovalWorkflow(id),
  onSettled: async (_data, error) => {
    if (!error) {
      await invalidateApprovalWorkflowLists();
    }
  }
});

export const activateApprovalWorkflowMutation = mutationOptions({
  mutationFn: (id: string) => activateApprovalWorkflow(id),
  onSettled: async (_data, error, id) => {
    if (!error) {
      await Promise.all([invalidateApprovalWorkflowLists(), invalidateApprovalWorkflowDetail(id)]);
    }
  }
});

export const deactivateApprovalWorkflowMutation = mutationOptions({
  mutationFn: (id: string) => deactivateApprovalWorkflow(id),
  onSettled: async (_data, error, id) => {
    if (!error) {
      await Promise.all([invalidateApprovalWorkflowLists(), invalidateApprovalWorkflowDetail(id)]);
    }
  }
});

export const createApprovalWorkflowStepMutation = mutationOptions({
  mutationFn: ({
    workflowId,
    values
  }: {
    workflowId: string;
    values: ApprovalStepMutationPayload;
  }) => createApprovalWorkflowStep(workflowId, values),
  onSettled: async (_data, error, variables) => {
    if (!error) {
      await Promise.all([
        invalidateApprovalWorkflowLists(),
        invalidateApprovalWorkflowDetail(variables.workflowId)
      ]);
    }
  }
});

export const updateApprovalWorkflowStepMutation = mutationOptions({
  mutationFn: ({
    workflowId,
    stepId,
    values
  }: {
    workflowId: string;
    stepId: string;
    values: ApprovalStepUpdatePayload;
  }) => updateApprovalWorkflowStep(workflowId, stepId, values),
  onSettled: async (_data, error, variables) => {
    if (!error) {
      await Promise.all([
        invalidateApprovalWorkflowLists(),
        invalidateApprovalWorkflowDetail(variables.workflowId)
      ]);
    }
  }
});

export const deleteApprovalWorkflowStepMutation = mutationOptions({
  mutationFn: ({ workflowId, stepId }: { workflowId: string; stepId: string }) =>
    deleteApprovalWorkflowStep(workflowId, stepId),
  onSettled: async (_data, error, variables) => {
    if (!error) {
      await Promise.all([
        invalidateApprovalWorkflowLists(),
        invalidateApprovalWorkflowDetail(variables.workflowId)
      ]);
    }
  }
});

export const reorderApprovalWorkflowStepsMutation = mutationOptions({
  mutationFn: ({
    workflowId,
    values
  }: {
    workflowId: string;
    values: ApprovalStepReorderPayload;
  }) => reorderApprovalWorkflowSteps(workflowId, values),
  onSettled: async (_data, error, variables) => {
    if (!error) {
      await Promise.all([
        invalidateApprovalWorkflowLists(),
        invalidateApprovalWorkflowDetail(variables.workflowId)
      ]);
    }
  }
});
