import { mutationOptions } from '@tanstack/react-query';
import { getQueryClient } from '@/lib/query-client';
import {
  activateDocumentTemplateVersion,
  archiveDocumentTemplateVersion,
  compareDocumentTemplateVersions,
  createDocumentTemplate,
  createDocumentTemplateMapping,
  createDocumentTemplateVersion,
  deleteDocumentTemplate,
  deleteDocumentTemplateMapping,
  duplicateDocumentTemplateVersion,
  previewDocumentTemplateVersion,
  publishDocumentTemplateVersion,
  rollbackDocumentTemplateVersion,
  setDocumentTemplateVersionActive,
  updateDocumentTemplate,
  updateDocumentTemplateMapping,
  updateDocumentTemplateVersion,
  validateDocumentTemplateVersion,
} from './service';
import { documentTemplateKeys } from './queries';
import type {
  DocumentTemplateMappingMutationPayload,
  DocumentTemplateMutationPayload,
  DocumentTemplateVersionMutationPayload,
} from './types';

async function invalidateTemplateLists() {
  await getQueryClient().invalidateQueries({ queryKey: documentTemplateKeys.lists() });
}

async function invalidateTemplateDetail(id: string) {
  await Promise.all([
    getQueryClient().invalidateQueries({ queryKey: documentTemplateKeys.detail(id) }),
    getQueryClient().invalidateQueries({ queryKey: documentTemplateKeys.versions(id) }),
  ]);
}

async function invalidateVersionManagement(versionId: string) {
  await getQueryClient().invalidateQueries({
    queryKey: documentTemplateKeys.management(versionId),
  });
}

export const createDocumentTemplateMutation = mutationOptions({
  mutationFn: (data: DocumentTemplateMutationPayload) => createDocumentTemplate(data),
  onSettled: async (_data, error) => {
    if (!error) {
      await invalidateTemplateLists();
    }
  }
});

export const updateDocumentTemplateMutation = mutationOptions({
  mutationFn: ({ id, values }: { id: string; values: Partial<DocumentTemplateMutationPayload> }) =>
    updateDocumentTemplate(id, values),
  onSettled: async (_data, error, variables) => {
    if (!error) {
      await Promise.all([invalidateTemplateLists(), invalidateTemplateDetail(variables.id)]);
    }
  }
});

export const deleteDocumentTemplateMutation = mutationOptions({
  mutationFn: (id: string) => deleteDocumentTemplate(id),
  onSettled: async (_data, error, id) => {
    if (!error) {
      const queryClient = getQueryClient();
      await invalidateTemplateLists();
      queryClient.removeQueries({ queryKey: documentTemplateKeys.detail(id) });
      queryClient.removeQueries({ queryKey: documentTemplateKeys.versions(id) });
    }
  }
});

export const createDocumentTemplateVersionMutation = mutationOptions({
  mutationFn: ({ id, values }: { id: string; values: DocumentTemplateVersionMutationPayload }) =>
    createDocumentTemplateVersion(id, values),
  onSettled: async (_data, error, variables) => {
    if (!error) {
      await Promise.all([invalidateTemplateLists(), invalidateTemplateDetail(variables.id)]);
    }
  }
});

export const updateDocumentTemplateVersionMutation = mutationOptions({
  mutationFn: ({
    templateId,
    versionId,
    values
  }: {
    templateId: string;
    versionId: string;
    values: Partial<DocumentTemplateVersionMutationPayload>;
  }) => {
    void templateId;
    return updateDocumentTemplateVersion(versionId, values);
  },
  onSettled: async (_data, error, variables) => {
    if (!error) {
      await Promise.all([invalidateTemplateLists(), invalidateTemplateDetail(variables.templateId)]);
    }
  }
});

export const setDocumentTemplateVersionActiveMutation = mutationOptions({
  mutationFn: ({
    templateId,
    versionId,
    isActive
  }: {
    templateId: string;
    versionId: string;
    isActive: boolean;
  }) => {
    void templateId;
    return setDocumentTemplateVersionActive(versionId, isActive);
  },
  onSettled: async (_data, error, variables) => {
    if (!error) {
      await Promise.all([invalidateTemplateLists(), invalidateTemplateDetail(variables.templateId)]);
    }
  }
});

export const createDocumentTemplateMappingMutation = mutationOptions({
  mutationFn: ({
    templateId,
    versionId,
    values
  }: {
    templateId: string;
    versionId: string;
    values: DocumentTemplateMappingMutationPayload;
  }) => {
    return createDocumentTemplateMapping(templateId, versionId, values);
  },
  onSettled: async (_data, error, variables) => {
    if (!error) {
      await Promise.all([invalidateTemplateLists(), invalidateTemplateDetail(variables.templateId)]);
    }
  }
});

export const updateDocumentTemplateMappingMutation = mutationOptions({
  mutationFn: ({
    templateId,
    mappingId,
    values
  }: {
    templateId: string;
    mappingId: string;
    values: Partial<DocumentTemplateMappingMutationPayload>;
  }) => {
    void templateId;
    return updateDocumentTemplateMapping(mappingId, values);
  },
  onSettled: async (_data, error, variables) => {
    if (!error) {
      await Promise.all([invalidateTemplateLists(), invalidateTemplateDetail(variables.templateId)]);
    }
  }
});

export const deleteDocumentTemplateMappingMutation = mutationOptions({
  mutationFn: ({ templateId, mappingId }: { templateId: string; mappingId: string }) => {
    void templateId;
    return deleteDocumentTemplateMapping(mappingId);
  },
  onSettled: async (_data, error, variables) => {
    if (!error) {
      await Promise.all([invalidateTemplateLists(), invalidateTemplateDetail(variables.templateId)]);
    }
  },
});

export const validateDocumentTemplateVersionMutation = mutationOptions({
  mutationFn: (versionId: string) => validateDocumentTemplateVersion(versionId),
});

export const publishDocumentTemplateVersionMutation = mutationOptions({
  mutationFn: ({
    templateId,
    versionId,
  }: {
    templateId: string;
    versionId: string;
  }) => publishDocumentTemplateVersion(versionId),
  onSettled: async (_data, error, variables) => {
    if (!error) {
      await Promise.all([
        invalidateTemplateLists(),
        invalidateTemplateDetail(variables.templateId),
        invalidateVersionManagement(variables.versionId),
      ]);
    }
  },
});

export const activateDocumentTemplateVersionMutation = mutationOptions({
  mutationFn: ({
    templateId,
    versionId,
  }: {
    templateId: string;
    versionId: string;
  }) => activateDocumentTemplateVersion(versionId),
  onSettled: async (_data, error, variables) => {
    if (!error) {
      await Promise.all([
        invalidateTemplateLists(),
        invalidateTemplateDetail(variables.templateId),
        invalidateVersionManagement(variables.versionId),
      ]);
    }
  },
});

export const rollbackDocumentTemplateVersionMutation = mutationOptions({
  mutationFn: ({
    templateId,
    versionId,
  }: {
    templateId: string;
    versionId: string;
  }) => rollbackDocumentTemplateVersion(versionId),
  onSettled: async (_data, error, variables) => {
    if (!error) {
      await Promise.all([
        invalidateTemplateLists(),
        invalidateTemplateDetail(variables.templateId),
        invalidateVersionManagement(variables.versionId),
      ]);
    }
  },
});

export const archiveDocumentTemplateVersionMutation = mutationOptions({
  mutationFn: ({
    templateId,
    versionId,
  }: {
    templateId: string;
    versionId: string;
  }) => archiveDocumentTemplateVersion(versionId),
  onSettled: async (_data, error, variables) => {
    if (!error) {
      await Promise.all([
        invalidateTemplateLists(),
        invalidateTemplateDetail(variables.templateId),
        invalidateVersionManagement(variables.versionId),
      ]);
    }
  },
});

export const duplicateDocumentTemplateVersionMutation = mutationOptions({
  mutationFn: ({
    templateId,
    versionId,
  }: {
    templateId: string;
    versionId: string;
  }) => duplicateDocumentTemplateVersion(versionId),
  onSettled: async (_data, error, variables) => {
    if (!error) {
      await Promise.all([
        invalidateTemplateLists(),
        invalidateTemplateDetail(variables.templateId),
        invalidateVersionManagement(variables.versionId),
      ]);
    }
  },
});

export const previewDocumentTemplateVersionMutation = mutationOptions({
  mutationFn: (versionId: string) => previewDocumentTemplateVersion(versionId),
});

export const compareDocumentTemplateVersionsMutation = mutationOptions({
  mutationFn: ({
    templateId,
    leftVersionId,
    rightVersionId,
  }: {
    templateId: string;
    leftVersionId: string;
    rightVersionId: string;
  }) => compareDocumentTemplateVersions(templateId, leftVersionId, rightVersionId),
});
