import { mutationOptions } from '@tanstack/react-query';
import { crmDashboardKeys } from '@/features/crm/dashboard/api/queries';
import { getQueryClient } from '@/lib/query-client';
import type {
  OpportunityAssignmentMutationPayload,
  OpportunityFollowupMutationPayload,
  OpportunityMarkCancelledPayload,
  OpportunityMarkLostPayload,
  OpportunityMarkNoQuotationPayload,
  OpportunityMarkWonPayload,
  OpportunityMutationPayload
} from './types';
import { opportunityKeys } from './queries';
import {
  assignOpportunity,
  createOpportunity,
  createOpportunityFollowup,
  deleteOpportunity,
  deleteOpportunityFollowup,
  markOpportunityCancelled,
  markOpportunityLost,
  markOpportunityNoQuotation,
  markOpportunityWon,
  reassignOpportunity,
  reopenOpportunity,
  updateOpportunity,
  updateOpportunityFollowup
} from './service';

async function invalidateOpportunityLists() {
  await getQueryClient().invalidateQueries({ queryKey: opportunityKeys.lists() });
}

async function invalidateDashboardQueries() {
  await getQueryClient().invalidateQueries({ queryKey: crmDashboardKeys.all });
}

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

async function invalidateOpportunityProjectParties(id: string) {
  await getQueryClient().invalidateQueries({ queryKey: opportunityKeys.projectParties(id) });
}

async function invalidateOpportunityFollowups(id: string) {
  await getQueryClient().invalidateQueries({ queryKey: opportunityKeys.followups(id) });
}

async function invalidateOpportunityAttachments(id: string) {
  await getQueryClient().invalidateQueries({ queryKey: opportunityKeys.attachments(id) });
}

export async function invalidateOpportunityMutationQueries(id: string) {
  await Promise.all([
    invalidateOpportunityLists(),
    invalidateOpportunityDetail(id),
    invalidateOpportunityProjectParties(id),
    invalidateOpportunityAttachments(id),
    invalidateDashboardQueries()
  ]);
}

export async function invalidateOpportunityFollowupMutationQueries(opportunityId: string) {
  await Promise.all([
    invalidateOpportunityLists(),
    invalidateOpportunityDetail(opportunityId),
    invalidateOpportunityFollowups(opportunityId),
    invalidateDashboardQueries()
  ]);
}

export const createOpportunityMutation = mutationOptions({
  mutationFn: (values: OpportunityMutationPayload) => createOpportunity(values),
  onSettled: async (_data, error) => {
    if (!error) {
      await Promise.all([invalidateOpportunityLists(), invalidateDashboardQueries()]);
    }
  }
});

export const updateOpportunityMutation = mutationOptions({
  mutationFn: ({ id, values }: { id: string; values: OpportunityMutationPayload }) =>
    updateOpportunity(id, values),
  onSettled: async (_data, error, variables) => {
    if (!error) {
      await invalidateOpportunityMutationQueries(variables.id);
    }
  }
});

export const deleteOpportunityMutation = mutationOptions({
  mutationFn: (id: string) => deleteOpportunity(id),
  onSettled: async (_data, error, id) => {
    if (!error) {
      await Promise.all([
        invalidateOpportunityLists(),
        invalidateDashboardQueries(),
        getQueryClient().removeQueries({ queryKey: opportunityKeys.detail(id) })
      ]);
    }
  }
});

export const assignOpportunityMutation = mutationOptions({
  mutationFn: ({ id, values }: { id: string; values: OpportunityAssignmentMutationPayload }) =>
    assignOpportunity(id, values),
  onSettled: async (_data, error, variables) => {
    if (!error) {
      await invalidateOpportunityMutationQueries(variables.id);
    }
  }
});

export const reassignOpportunityMutation = mutationOptions({
  mutationFn: ({ id, values }: { id: string; values: OpportunityAssignmentMutationPayload }) =>
    reassignOpportunity(id, values),
  onSettled: async (_data, error, variables) => {
    if (!error) {
      await invalidateOpportunityMutationQueries(variables.id);
    }
  }
});

export const createOpportunityFollowupMutation = mutationOptions({
  mutationFn: ({
    opportunityId,
    values
  }: {
    opportunityId: string;
    values: OpportunityFollowupMutationPayload;
  }) => createOpportunityFollowup(opportunityId, values),
  onSettled: async (_data, error, variables) => {
    if (!error) {
      await invalidateOpportunityFollowupMutationQueries(variables.opportunityId);
    }
  }
});

export const updateOpportunityFollowupMutation = mutationOptions({
  mutationFn: ({
    opportunityId,
    followupId,
    values
  }: {
    opportunityId: string;
    followupId: string;
    values: OpportunityFollowupMutationPayload;
  }) => updateOpportunityFollowup(opportunityId, followupId, values),
  onSettled: async (_data, error, variables) => {
    if (!error) {
      await invalidateOpportunityFollowupMutationQueries(variables.opportunityId);
    }
  }
});

export const deleteOpportunityFollowupMutation = mutationOptions({
  mutationFn: ({ opportunityId, followupId }: { opportunityId: string; followupId: string }) =>
    deleteOpportunityFollowup(opportunityId, followupId),
  onSettled: async (_data, error, variables) => {
    if (!error) {
      await invalidateOpportunityFollowupMutationQueries(variables.opportunityId);
    }
  }
});

export const markOpportunityWonMutation = mutationOptions({
  mutationFn: ({ id, values }: { id: string; values: OpportunityMarkWonPayload }) =>
    markOpportunityWon(id, values),
  onSettled: async (_data, error, variables) => {
    if (!error) {
      await invalidateOpportunityMutationQueries(variables.id);
    }
  }
});

export const markOpportunityLostMutation = mutationOptions({
  mutationFn: ({ id, values }: { id: string; values: OpportunityMarkLostPayload }) =>
    markOpportunityLost(id, values),
  onSettled: async (_data, error, variables) => {
    if (!error) {
      await invalidateOpportunityMutationQueries(variables.id);
    }
  }
});

export const markOpportunityCancelledMutation = mutationOptions({
  mutationFn: ({ id, values }: { id: string; values: OpportunityMarkCancelledPayload }) =>
    markOpportunityCancelled(id, values),
  onSettled: async (_data, error, variables) => {
    if (!error) {
      await invalidateOpportunityMutationQueries(variables.id);
    }
  }
});

export const markOpportunityNoQuotationMutation = mutationOptions({
  mutationFn: ({ id, values }: { id: string; values: OpportunityMarkNoQuotationPayload }) =>
    markOpportunityNoQuotation(id, values),
  onSettled: async (_data, error, variables) => {
    if (!error) {
      await invalidateOpportunityMutationQueries(variables.id);
    }
  }
});

export const reopenOpportunityMutation = mutationOptions({
  mutationFn: ({ id, reason }: { id: string; reason: string }) =>
    reopenOpportunity(id, { reopenReason: reason }),
  onSettled: async (_data, error, variables) => {
    if (!error) {
      await invalidateOpportunityMutationQueries(variables.id);
    }
  }
});
