import { create } from 'zustand';
import axiosInstance from '@/utils/axios';
import { endpoints } from '../../endpoints/admin-service';
import {
    AgencyList, AgencyPageFilterParams, AgencyNames, DepartmentNames, LotNumbers, Sector, SectorList, SectorPageFilterParams,
    SectorRequest, AgencyRequest, Agency, SectorNames, Department, DepartmentList, DepartmentPageFilterParams, DepartmentRequest,
    LotList, LotPageFilterParams, Lot, LotRequest
} from '@/shared/types/infrastructure';

type InfrastructureStore = {
    error: string | null;
    loading: boolean;
    sectorNames: SectorNames[];
    fetchSectorNames: () => Promise<void>;
    agencyNames: AgencyNames[];
    fetchAgencyNames: () => Promise<void>;
    departmentNames: DepartmentNames[];
    fetchDepartmentNames: () => Promise<void>;
    lotNumbers: LotNumbers[];
    fetchLotNumbers: () => Promise<void>;
    departmentNamesByAgencyId: DepartmentNames[];
    fetchDepartmentNamesByAgencyId: (agencyId: number) => Promise<void>;
    lotNumbersByDepartmentId: LotNumbers[];
    fetchLotNumbersByDepartmentId: (departmentId: number) => Promise<void>;
    sectorPage: SectorList[];
    sectorPageTotalElements: number;
    fetchSectorPage: (params: SectorPageFilterParams) => Promise<void>;
    toggleSectorActivation: (sectorId: string, isActive: boolean) => Promise<void>;
    sectorById: Sector | null;
    getSectorById: (sectorId: string) => Promise<Sector | null>;
    createSector: (sector: SectorRequest) => Promise<void>;
    updateSector: (sectorId: string, sector: SectorRequest) => Promise<void>;
    agencyPage: AgencyList[];
    agencyPageTotalElements: number;
    fetchAgencyPage: (params: AgencyPageFilterParams) => Promise<void>;
    toggleAgencyActivation: (agencyId: string, isActive: boolean) => Promise<void>;
    agencyById: Agency | null;
    getAgencyById: (agencyId: string) => Promise<Agency | null>;
    createAgency: (agency: AgencyRequest) => Promise<void>;
    updateAgency: (agencyId: string, agency: AgencyRequest) => Promise<void>;
    departmentPage: DepartmentList[];
    departmentPageTotalElements: number;
    fetchDepartmentPage: (params: DepartmentPageFilterParams) => Promise<void>;
    toggleDepartmentActivation: (departmentId: string, isActive: boolean) => Promise<void>;
    departmentById: Department | null;
    getDepartmentById: (departmentId: string) => Promise<Department | null>;
    createDepartment: (department: DepartmentRequest) => Promise<void>;
    updateDepartment: (departmentId: string, department: DepartmentRequest) => Promise<void>;
    lotPage: LotList[];
    lotPageTotalElements: number;
    fetchLotPage: (params: LotPageFilterParams) => Promise<void>;
    toggleLotActivation: (lotId: string, isActive: boolean) => Promise<void>;
    lotById: Lot | null;
    getLotById: (lotId: string) => Promise<Lot | null>;
    createLot: (lot: LotRequest) => Promise<void>;
    updateLot: (lotId: string, lot: LotRequest) => Promise<void>;
    startExportInfrastructureDataInExcel: (params: SectorPageFilterParams) => Promise<void>;
    exportInfrastructureDataInPdf: (params: SectorPageFilterParams) => Promise<void>;
};

export const useInfrastructureStore = create<InfrastructureStore>((set) => ({
    error: null,
    loading: false,
    sectorNames: [],
    fetchSectorNames: async () => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.get<SectorNames[]>(endpoints.Admin.Infrastructure.Sector.getSectorNamesAndIds);
            set({ sectorNames: response.data, loading: false });
        } catch (error: any) {
            set({ error: error.message || 'Failed to fetch sector names', loading: false });
        }
    },
    agencyNames: [],
    fetchAgencyNames: async () => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.get<AgencyNames[]>(endpoints.Admin.Infrastructure.Agency.getAgencyNamesAndIds);
            set({ agencyNames: response.data, loading: false });
        } catch (error: any) {
            set({ error: error.message || 'Failed to fetch agency names', loading: false });
        }
    },
    departmentNames: [],
    fetchDepartmentNames: async () => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.get<DepartmentNames[]>(endpoints.Admin.Infrastructure.Department.getDepartmentNamesAndIds);
            set({ departmentNames: response.data, loading: false });
        } catch (error: any) {
            set({ error: error.message || 'Failed to fetch department names', loading: false });
        }
    },
    departmentNamesByAgencyId: [],
    fetchDepartmentNamesByAgencyId: async (agencyId: number) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.get<DepartmentNames[]>(endpoints.Admin.Infrastructure.Department.getDepartmentNamesAndIdsByAgencyId(agencyId));
            set({ departmentNamesByAgencyId: response.data, loading: false });
        } catch (error: any) {
            set({ error: error.message || 'Failed to fetch department names by agency id', loading: false });
        }
    },
    lotNumbers: [],
    fetchLotNumbers: async () => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.get<LotNumbers[]>(endpoints.Admin.Infrastructure.Lot.getLotNumbersAndIds);
            set({ lotNumbers: response.data, loading: false });
        } catch (error: any) {
            set({ error: error.message || 'Failed to fetch lot numbers', loading: false });
        }
    },
    lotNumbersByDepartmentId: [],
    fetchLotNumbersByDepartmentId: async (departmentId: number) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.get<LotNumbers[]>(endpoints.Admin.Infrastructure.Lot.getLotNumbersAndIdsByDepartmentId(departmentId));
            set({ lotNumbersByDepartmentId: response.data, loading: false });
        } catch (error: any) {
            set({ error: error.message || 'Failed to fetch lot numbers by department id', loading: false });
        }
    },
    sectorPage: [],
    sectorPageTotalElements: 0,
    fetchSectorPage: async (params) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.get(endpoints.Admin.Infrastructure.Sector.getSectorsPage, {
                params,
            });

            const { content, totalElements } = response.data;
            set({
                sectorPage: content,
                sectorPageTotalElements: totalElements,
                loading: false,
            });
        } catch (error: any) {
            set({
                error: error.message || 'Failed to fetch contracts',
                loading: false,
            });
        }
    },
    toggleSectorActivation: async (sectorId: string, isActive: boolean) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.post<boolean>(endpoints.Admin.Infrastructure.Sector.toggleSectorActivation(sectorId, isActive));
            set((state) => ({
                sectorPage: state.sectorPage.map((s) => (s.id === sectorId ? { ...s, active: response.data } : s)),
                loading: false,
            }));
        } catch (error: any) {
            set({ error: error.message || 'Failed to toggle sector active', loading: false });
        }
    },
    sectorById: null,
    getSectorById: async (id) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.get(endpoints.Admin.Infrastructure.Sector.getSectorById(id));
            set({ loading: false, sectorById: response.data as Sector });
            return response.data as Sector;
        } catch (error: any) {
            set({
                error: error.message || 'Failed to fetch sector by ID',
                loading: false,
            });
            return null;
        }
    },
    createSector: async (sector: SectorRequest) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.post(endpoints.Admin.Infrastructure.Sector.createSector, sector);
            set((state) => ({
                sectorPage: [...state.sectorPage, response.data],
                loading: false,
            }));
        } catch (error: any) {
            set({ error: error.message || 'Failed to create sector', loading: false });
        }
    },
    updateSector: async (sectorId: string, sector: SectorRequest) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.post(endpoints.Admin.Infrastructure.Sector.updateSector(sectorId), sector);
            set((state) => ({
                sectorPage: state.sectorPage.map((s) => (s.id === sectorId ? response.data : s)),
                loading: false,
            }));
        } catch (error: any) {
            set({ error: error.message || 'Failed to update sector', loading: false });
        }
    },
    agencyPage: [],
    agencyPageTotalElements: 0,
    fetchAgencyPage: async (params) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.get(endpoints.Admin.Infrastructure.Agency.getAgencyPage, {
                params,
            });
            const { content, totalElements } = response.data;
            set({
                agencyPage: content,
                agencyPageTotalElements: totalElements,
                loading: false,
            });
        } catch (error: any) {
            set({
                error: error.message || 'Failed to fetch agency page',
                loading: false,
            });
        }
    },
    toggleAgencyActivation: async (agencyId: string, isActive: boolean) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.post<boolean>(endpoints.Admin.Infrastructure.Agency.toggleAgencyActivation(agencyId, isActive));
            set((state) => ({
                agencyPage: state.agencyPage.map((a) => (a.id === agencyId ? { ...a, active: response.data } : a)),
                loading: false,
            }));
        } catch (error: any) {
            set({ error: error.message || 'Failed to toggle agency active', loading: false });
        }
    },
    agencyById: null,
    getAgencyById: async (id) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.get(endpoints.Admin.Infrastructure.Agency.getAgencyById(id));
            set({ loading: false, agencyById: response.data as Agency });
            return response.data as Agency;
        } catch (error: any) {
            set({
                error: error.message || 'Failed to fetch agency by ID',
                loading: false,
            });
            return null;
        }
    },
    createAgency: async (agency: AgencyRequest) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.post(endpoints.Admin.Infrastructure.Agency.createAgency, agency);
            set((state) => ({
                agencyPage: [...state.agencyPage, response.data],
                loading: false,
            }));
        } catch (error: any) {
            set({ error: error.message || 'Failed to create agency', loading: false });
        }
    },
    updateAgency: async (agencyId: string, agency: AgencyRequest) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.post(endpoints.Admin.Infrastructure.Agency.updateAgency(agencyId), agency);
            set((state) => ({
                agencyPage: state.agencyPage.map((a) => (a.id === agencyId ? response.data : a)),
                loading: false,
            }));
        } catch (error: any) {
            set({ error: error.message || 'Failed to update agency', loading: false });
        }
    },
    departmentPage: [],
    departmentPageTotalElements: 0,
    fetchDepartmentPage: async (params) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.get(endpoints.Admin.Infrastructure.Department.getDepartmentPage, {
                params,
            });
            const { content, totalElements } = response.data;
            set({
                departmentPage: content,
                departmentPageTotalElements: totalElements,
                loading: false,
            });
        } catch (error: any) {
            set({
                error: error.message || 'Failed to fetch department page',
                loading: false,
            });
        }
    },
    toggleDepartmentActivation: async (departmentId: string, isActive: boolean) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.post<boolean>(endpoints.Admin.Infrastructure.Department.toggleDepartmentActivation(departmentId, isActive));
            set((state) => ({
                departmentPage: state.departmentPage.map((d) => (d.id === departmentId ? { ...d, active: response.data } : d)),
                loading: false,
            }));
        } catch (error: any) {
            set({ error: error.message || 'Failed to toggle department active', loading: false });
        }
    },
    departmentById: null,
    getDepartmentById: async (id) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.get(endpoints.Admin.Infrastructure.Department.getDepartmentById(id));
            set({ loading: false, departmentById: response.data as Department });
            return response.data as Department;
        } catch (error: any) {
            set({
                error: error.message || 'Failed to fetch department by ID',
                loading: false,
            });
            return null;
        }
    },
    createDepartment: async (department: DepartmentRequest) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.post(endpoints.Admin.Infrastructure.Department.createDepartment, department);
            set((state) => ({
                departmentPage: [...state.departmentPage, response.data],
                loading: false,
            }));
        } catch (error: any) {
            set({ error: error.message || 'Failed to create department', loading: false });
        }
    },
    updateDepartment: async (departmentId: string, department: DepartmentRequest) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.post(endpoints.Admin.Infrastructure.Department.updateDepartment(departmentId), department);
            set((state) => ({
                departmentPage: state.departmentPage.map((d) => (d.id === departmentId ? response.data : d)),
                loading: false,
            }));
        } catch (error: any) {
            set({ error: error.message || 'Failed to update department', loading: false });
        }
    },
    lotPage: [],
    lotPageTotalElements: 0,
    fetchLotPage: async (params) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.get(endpoints.Admin.Infrastructure.Lot.getLotPage, {
                params,
            });
            const { content, totalElements } = response.data;
            set({
                lotPage: content,
                lotPageTotalElements: totalElements,
                loading: false,
            });
        } catch (error: any) {
            set({
                error: error.message || 'Failed to fetch lot page',
                loading: false,
            });
        }
    },
    toggleLotActivation: async (lotId: string, isActive: boolean) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.post<boolean>(endpoints.Admin.Infrastructure.Lot.toggleLotActivation(lotId, isActive));
            set((state) => ({
                lotPage: state.lotPage.map((l) => (l.id === lotId ? { ...l, active: response.data } : l)),
                loading: false,
            }));
        } catch (error: any) {
            set({ error: error.message || 'Failed to toggle lot active', loading: false });
        }
    },
    lotById: null,
    getLotById: async (id) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.get(endpoints.Admin.Infrastructure.Lot.getLotById(id));
            set({ loading: false, lotById: response.data as Lot });
            return response.data as Lot;
        } catch (error: any) {
            set({
                error: error.message || 'Failed to fetch lot by ID',
                loading: false,
            });
            return null;
        }
    },
    createLot: async (lot: LotRequest) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.post(endpoints.Admin.Infrastructure.Lot.createLot, lot);
            set((state) => ({
                lotPage: [...state.lotPage, response.data],
                loading: false,
            }));
        } catch (error: any) {
            set({ error: error.message || 'Failed to create lot', loading: false });
        }
    },
    updateLot: async (lotId: string, lot: LotRequest) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.post(endpoints.Admin.Infrastructure.Lot.updateLot(lotId), lot);
            set((state) => ({
                lotPage: state.lotPage.map((l) => (l.id === lotId ? response.data : l)),
                loading: false,
            }));
        } catch (error: any) {
            set({ error: error.message || 'Failed to update lot', loading: false });
        }
    },
    startExportInfrastructureDataInExcel: async (params: SectorPageFilterParams) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.get(endpoints.Admin.Infrastructure.Sector.startExportInfrastructureDataInExcel, {
                params,
                responseType: 'blob'
            });
            const blob = new Blob([response.data], { type: 'text/csv;charset=utf-8;' });
            const url = window.URL.createObjectURL(blob);
            const link = document.createElement('a');
            link.href = url;
            link.setAttribute('download', 'secteurs.csv');
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
            window.URL.revokeObjectURL(url);
            set({ loading: false });
        } catch (error: any) {
            set({ error: error.message || 'Failed to export infrastructure data in csv', loading: false });
        }
    },
    exportInfrastructureDataInPdf: async (params: SectorPageFilterParams) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.get(endpoints.Admin.Infrastructure.Sector.exportInfrastructureDataInPdf, {
                params,
                responseType: 'blob'
            });
            const blob = new Blob([response.data], { type: 'application/pdf' });
            const url = window.URL.createObjectURL(blob);
            const link = document.createElement('a');
            link.href = url;
            link.setAttribute('download', 'secteurs.pdf');
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
            window.URL.revokeObjectURL(url);
            set({ loading: false });
        } catch (error: any) {
            set({ error: error.message || 'Failed to export infrastructure data in pdf', loading: false });
        }
    }
}));