import axiosInstance from "@/utils/axios";
import { create } from "zustand";
import { circuitEndpoints } from "../../endpoints/circuit";
import { Circuit, CircuitState, ITripShort, SaveCircuit, SearchCircuitParams, TripCircuitDTO, WeekTypeSchedule, ExportCircuitParams, GenerateTripStatusDTO } from "@/shared/types/circuit";

export interface CircuitAutocompleteResponse {
    id: string;
    circuitCode: string;
}

export interface CircuitWithSpecificInfoResponse {
    id: string;
    circuitCode: string;
    titled: string;
}

export interface SearchTripParams {
    circuitId: string;
    sortBy?: string;
    sortDirection?: 'asc' | 'desc';
    page?: number;
    size?: number;
}

type CircuitStore = {
    circuits: Circuit[];
    circuit: Circuit | null;
    loading: boolean;
    generateTripsLoading: boolean;
    recalculateLoading: boolean;
    error: string | null;
    totalElements: number;
    totalElementsTrips: number;
    trips: TripCircuitDTO[];
    lastUsedCircuitParams: SearchCircuitParams | null;
    lastUsedTripParams: SearchTripParams | null;
    searchCircuit: (params?: SearchCircuitParams, signal?: AbortSignal) => Promise<void>;
    addCircuit: (circuit: SaveCircuit) => Promise<Circuit>;
    updateCircuit: (circuit: Circuit) => Promise<void>;
    toggleActive: (circuitCode: string) => Promise<void>;
    updateCircuitStatus: (id: string, circuitState: CircuitState) => Promise<void>;
    getCircuitByCode: (circuitCode: string) => Promise<Circuit>;
    autocompleteCircuits: (circuitCode?: string) => Promise<CircuitAutocompleteResponse[]>;
    searchWithSpecificInfoByCircuitCode: (keyword?: string, id?: string) => Promise<CircuitWithSpecificInfoResponse[]>;
    generateTrips: (circuitId: string) => Promise<void>;
    canGenerateTrips: (circuitId: string) => Promise<GenerateTripStatusDTO>;
    getTrips: (params: SearchTripParams) => Promise<void>;
    getTripsByDriverIdAndDate: (driverId: number, year: number, month: number) => Promise<ITripShort[]>;
    getTripsByCircuitAndSchedule: (circuitId: string, schedules: WeekTypeSchedule[], startDate: string, endDate: string) => Promise<ITripShort[]>;
    getCircuitColorByCircuitCode: (circuitCode: string) => Promise<string>;
    recalculateTrip: (tripId: string) => Promise<string>;
    exportCircuits: (params: ExportCircuitParams) => Promise<void>;
    getDriverCircuits: (driverId: number, date : string ) => Promise<Circuit[]>;
};

export const useCircuitStore = create<CircuitStore>((set, get) => ({
    circuits: [],
    circuit: null,
    loading: false,
    generateTripsLoading: false,
    error: null,
    totalElements: 0,
    totalElementsTrips: 0,
    trips: [],
    lastUsedCircuitParams: null,
    lastUsedTripParams: null,
    searchCircuit: async (params, externalSignal) => {
        set({ error: null, loading: true, lastUsedCircuitParams: params });

        try {
            const response = await axiosInstance.get(circuitEndpoints.circuit.search, {
                params,
                signal: externalSignal,
            });

            if (!externalSignal?.aborted) {
                const { content, totalElements } = response.data;
                set({
                    circuits: content,
                    totalElements,
                    loading: false,
                });
            }
        } catch (error: any) {
            if (error.name !== "CanceledError" && error.code !== "ERR_CANCELED") {
                set({
                    error: error.message || "Erreur lors de la recherche des circuits",
                    loading: false,
                });
                throw error;
            }
        }
    },
    addCircuit: async (circuit: SaveCircuit) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.post(circuitEndpoints.circuit.add, circuit);
            const { lastUsedCircuitParams, searchCircuit } = get();
            if (lastUsedCircuitParams) {
                await searchCircuit(lastUsedCircuitParams);
            }
            set({ loading: false });
            return response.data;
        } catch (error: any) {
            set({
                error: error.message || 'Erreur lors de l\'ajout du circuit',
                loading: false,
            });
            throw error;
        }
    },

    updateCircuit: async (circuit: Circuit) => {
        set({ loading: true, error: null });
        try {
            await axiosInstance.put(circuitEndpoints.circuit.update, circuit);
            set((state) => ({
                circuits: state.circuits.map((c) => (c.id === circuit.id ? circuit : c)),
                loading: false,
            }));
        } catch (error: any) {
            set({
                error: error.message || 'Erreur lors de la mise à jour du circuit',
                loading: false,
            });
            throw error;
        }
    },

    toggleActive: async (id: string) => {
        set({ loading: true, error: null });
        try {
            await axiosInstance.put<boolean>(circuitEndpoints.circuit.toggleActive(id));
            set((state) => ({
                circuits: state.circuits.map((c) => (c.id === id ? { ...c, active: !c.active } : c)),
                loading: false,
            }));
        } catch (error: any) {
            set({
                error: error.message || 'Erreur lors du changement de statut',
                loading: false,
            });
            throw error;
        }
    },

    updateCircuitStatus: async (id, circuitState) => {
        set({ loading: true, error: null });
        try {
            await axiosInstance.put<CircuitState>(
                circuitEndpoints.circuit.updateStatus(id), null, { params: { circuitState } }
            );
            set((state) => ({
                circuits: state.circuits.map((c) => (c.id === id ? { ...c, circuitState: circuitState } : c)),
                loading: false,
            }));
        } catch (error: any) {
            set({
                error: error.message || 'Failed to update circuit status',
                loading: false,
            });
            throw error;
        }
    },

    getCircuitByCode: async (circuitCode: string) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.get<Circuit>(circuitEndpoints.circuit.getByCode(circuitCode));
            set({ loading: false });
            return response.data;
        } catch (error: any) {
            set({
                error: error.message || 'Erreur lors de la récupération du circuit',
                loading: false,
            });
            throw error;
        }
    },

    autocompleteCircuits: async (circuitCode?: string) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.get(circuitEndpoints.circuit.autocomplete, {
                params: { circuitCode },
            });
            set({ loading: false });
            return response.data;
        } catch (error: any) {
            set({
                error: error.message || 'Erreur lors de la recherche des circuits',
                loading: false,
            });
            throw error;
        }
    },
    searchWithSpecificInfoByCircuitCode: async (keyword?: string, id?: string) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.get(circuitEndpoints.circuit.searchWithSpecificInfoByCircuitCode, {
                params: { keyword, id },
            });
            set({ loading: false });
            return response.data;
        } catch (error: any) {
            set({
                error: error.message || 'Erreur lors de la recherche des circuits avec informations spécifiques',
                loading: false,
            });
            throw error;
        }
    },
    generateTrips: async (circuitId: string) => {
        set({ generateTripsLoading: true, error: null });
        try {
            await axiosInstance.get(circuitEndpoints.circuit.trip.generateTrips(circuitId));
            set({ generateTripsLoading: false });
        } catch (error: any) {
            set({ error: error.message || 'Erreur lors de la génération des trajets', generateTripsLoading: false });
            throw error;
        }
    },
    canGenerateTrips: async (circuitId: string) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.get<GenerateTripStatusDTO>(
                circuitEndpoints.circuit.trip.canGenerateTrips(circuitId)
            );
            set({ loading: false });
            return response.data;
        } catch (error: any) {
            set({
                error: error.message || 'Erreur lors de la vérification de la génération des trajets',
                loading: false,
            });
            throw error;
        }
    },
    getTrips: async (params: SearchTripParams) => {
        const { circuitId, ...rest } = params;
        set({ loading: true, error: null, lastUsedTripParams: params });
        try {
            const response = await axiosInstance.get(circuitEndpoints.circuit.trip.getTrips(circuitId), { params: rest });
            set({
                loading: false,
                trips: response.data,
                totalElementsTrips: response.data.length,
            });
            return response.data;
        } catch (error: any) {
            set({ error: error.message || 'Erreur lors de la récupération des trajets', loading: false, trips: [] });
            throw error;
        }
    },
    getTripsByDriverIdAndDate: async (driverId, year, month) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.get<ITripShort[]>(
                circuitEndpoints.circuit.trip.getShortTrip,
                {
                    params: { driverId, year, month },
                }
            );
            set({ loading: false });
            return response.data;
        } catch (error: any) {
            set({
                error: error.message || "Erreur lors de la récupération des trajets du chauffeur",
                loading: false,
            });
            throw error;
        }
    },

    getTripsByCircuitAndSchedule: async (circuitId, schedules, startDate, endDate) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.post<ITripShort[]>(
                circuitEndpoints.circuit.trip.getTripsByCircuitAndSchedule,
                schedules,
                {
                    params: { circuitId, startDate, endDate },
                }
            );
            set({ loading: false });
            return response.data;
        } catch (error: any) {
            set({
                error: error.message || "Erreur lors de la récupération des trajets par circuit et planning",
                loading: false,
            });
            throw error;
        }
    },
    getCircuitColorByCircuitCode: async (circuitCode: string) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.get(circuitEndpoints.circuit.getCircuitColorByCircuitCode(circuitCode));
            set({ loading: false });
            return response.data;
        } catch (error: any) {
            set({ error: error.message || 'Erreur lors de la récupération de la couleur du circuit', loading: false });
            throw error;
        }
    },
    recalculateLoading: false,
    recalculateTrip: async (tripId) => {
        set({ recalculateLoading: true, error: null });
        try {
            const response = await axiosInstance.post(
                circuitEndpoints.circuit.trip.recalculateTrip(tripId)
            );
            const updateTripsInBackground = async () => {
                try {
                    const { getTrips, lastUsedTripParams } = get();
                    if (lastUsedTripParams) {
                        await getTrips(lastUsedTripParams);
                    }
                } catch (error) {
                    console.error('Erreur mise à jour liste trajets:', error);
                }
            };
            
            updateTripsInBackground();
            set({ recalculateLoading: false });
            return response.data.id;
        } catch (error: any) {
            set({
                recalculateLoading: false,
                error: error.message || 'Erreur lors du recalcul du trajet',
            });
            throw error;
        }
    },
    exportCircuits: async (params: ExportCircuitParams) => {
        set({ error: null });
        try {
            await axiosInstance.post(circuitEndpoints.circuit.export, null, { params });

        } catch (error: any) {
            set({
                error: error.message || 'Erreur lors de l\'exportation des circuits',

            });
            throw error;
        }
    },
    getDriverCircuits: async (driverId: number, date: string) => {
  set({ loading: true, error: null });
  try {
    const response = await axiosInstance.get(circuitEndpoints.circuit.getDriverCircuit, {
      params: {
        driverId: driverId,     
        date: date,      },
    });
    set({
      loading: false,
      circuits: response.data,
    });
    return response.data; 
  } catch (error: any) {
    set({
      error: error.message || 'Erreur lors de la récupération des circuits affectés au chauffeur',
      loading: false,
    });
    throw error;
  }
},
}));
