import { create } from 'zustand';
import axiosInstance from '@/utils/axios';
import { Contract, ContractList, ContractPageFilterParams, ContractRequest, ContractStatus, ShortContract } from '@/shared/types/contract';
import { contractEndpoints } from '../../endpoints/admin-service/contract-endpoints';


type ContractStore = {
  loading: boolean;
  error: string | null;
  clearError: () => void;
  contracts: ContractList[];
  shortContracts: ShortContract[];
  totalElements: number;
  lastUsedContractParams: ContractPageFilterParams | null;
  fetchContractsPage: (params?: ContractPageFilterParams) => Promise<void>;
  contractById: Contract | null;
  getContractById: (id: string) => Promise<Contract | null>;
  createContract: (contract: ContractRequest) => Promise<void>;
  toogleActivation: (id: string, isActive: boolean) => Promise<void>;
  updateContract: (id: string, contract: ContractRequest) => Promise<void>;
  startExportFiltredContracts: (params?: ContractPageFilterParams) => Promise<void>;
  updateContractStatus: (id: string, newStatus: ContractStatus) => Promise<void>;
  searchContractByTitle: (contractId: string | null) => Promise<ShortContract[]>;
  existsContractByTitleLoading: boolean;
  existsContractByTitle: (title: string, excludeId?: number) => Promise<boolean>;
  existsContractByCodeLoading: boolean;
  existsContractByCode: (code: string, excludeId?: number) => Promise<boolean>;
};

export const useContractStore = create<ContractStore>((set, get) => ({
  loading: false,
  error: null,
  clearError: () => set({ error: null }),
  contracts: [],
  shortContracts: [],
  totalElements: 0,
  lastUsedContractParams: null,
  fetchContractsPage: async (params) => {
    set({ loading: true, error: null });
    set({ lastUsedContractParams: params });
    try {
      const response = await axiosInstance.get(contractEndpoints.getContractsPage, {
        params,
      });

      const { content, totalElements } = response.data;
      set({
        contracts: content,
        totalElements,
        loading: false,
      });
    } catch (error: any) {
      set({
        error: error.message || 'Failed to fetch contracts',
        loading: false,
      });
    }
  },
  contractById: null,
  getContractById: async (id) => {
    set({ loading: true, error: null });
    try {
      const response = await axiosInstance.get(contractEndpoints.getContractById(id));
      set({ loading: false, contractById: response.data as Contract });
      return response.data as Contract;
    } catch (error: any) {
      set({
        error: error.message || 'Failed to fetch contract by ID',
        loading: false,
      });
      return null;
    }
  },
  createContract: async (contract) => {
    set({ loading: true, error: null });
    try {
      await axiosInstance.post(contractEndpoints.createContract, contract);
      const { lastUsedContractParams, fetchContractsPage } = get();
      if (lastUsedContractParams) {
        await fetchContractsPage(lastUsedContractParams);
      }
      set({ loading: false });
    } catch (error: any) {
      set({
        error: error.message || 'Failed to create contract',
        loading: false,
      });
    }
  },
  toogleActivation: async (id, isActive) => {
    set({ loading: true, error: null });
    try {
      const response = await axiosInstance.patch<boolean>(contractEndpoints.toogleActivation(id, isActive));
      set((state) => ({
        contracts: state.contracts.map((c) => (c.id === id ? { ...c, active: response.data } : c)),
        loading: false,
      }));
    } catch (error: any) {
      set({
        error: error.message || 'Failed to toggle activation',
        loading: false,
      });
    }
  },
  updateContract: async (id, contract) => {
    set({ loading: true, error: null });
    try {
      await axiosInstance.put<ContractStatus>(contractEndpoints.updateContract(id), contract);
      const { lastUsedContractParams, fetchContractsPage } = get();
      if (lastUsedContractParams) {
        await fetchContractsPage(lastUsedContractParams);
      }
      set({ loading: false });
    } catch (error: any) {
      set({
        error: error.message || 'Failed to update contract',
        loading: false,
      });
    }
  },
  startExportFiltredContracts: async (params) => {
    set({ loading: true, error: null });
    try {
      const userId = typeof window !== 'undefined' ? localStorage.getItem('userId') : null;
      const response = await axiosInstance.post(
        contractEndpoints.startExportFiltredContracts,
        { params },
        userId ? { params: { userId } } : undefined
      );
      return response.data;
    } catch (error: any) {
      set({
        error: error.message || 'Failed to start export contracts',
        loading: false,
      });
    }
  },
  updateContractStatus: async (id, newStatus) => {
    set({ loading: true, error: null });
    try {
      await axiosInstance.patch<ContractStatus>(
        contractEndpoints.updateContractStatus(id), null, { params: { newStatus } }
      );
      const { lastUsedContractParams, fetchContractsPage } = get();
      if (lastUsedContractParams) {
        await fetchContractsPage(lastUsedContractParams);
      }
      set({ loading: false });
    } catch (error: any) {
      set({
        error: error.message || 'Failed to update contract status',
        loading: false,
      });
    }
  },

  searchContractByTitle: async (contractTitle) => {
    set({ loading: true, error: null })
    try {
      const response = await axiosInstance.get(contractEndpoints.searchContractByTitle(), {
        params: { title: contractTitle }
      })
      set({ loading: false })
      return response.data
    } catch (error: any) {
      set({
        error: error.message || "Failed to search contract by title",
        loading: false,
      })
      throw error
    }
  },
  existsContractByTitleLoading: false,
  existsContractByTitle: async (title: string, excludeId?: number) => {
    set({ existsContractByTitleLoading: true, error: null });
    try {
      const response = await axiosInstance.get(
        contractEndpoints.existsContractByTitle,
        { params: { title, excludeId } }
      );
      return response.data;
    } catch (error: any) {
      set({
        error: error.message || "Failed to check if contract exists by title",
      });
      throw error;
    } finally {
      set({ existsContractByTitleLoading: false });
    }
  },
  existsContractByCodeLoading: false,
  existsContractByCode: async (code: string, excludeId?: number) => {
    set({ existsContractByCodeLoading: true, error: null });
    try {
      const response = await axiosInstance.get(
        contractEndpoints.existsContractByCode,
        { params: { code, excludeId } }
      );
      return response.data;
    } catch (error: any) {
      set({
        error: error.message || "Failed to check if contract exists by code",
      });
      throw error;
    } finally {
      set({ existsContractByCodeLoading: false });
    }
  }
}));
