import axiosInstance from "@/utils/axios";
import dayjs from "dayjs";
import { create } from "zustand";
import { 
  ITripDriverAssignment, 
  ITripDriverAssignmentList, 
  TripDriverAssignmentSearchParams,
  DriverAssignmentRequestDTO,
  TripRankingResponse,
  CircuitRankingResponse,
  ITripDriverAssignmentDetails,
  DriverSearchRequestDTO,
  DriverMapResponseDTO,
  MultipleTripsRankingResponse
} from "@/shared/types/circuit";
import { circuitEndpoints } from "../../endpoints/circuit";

interface TripDriverAssignmentStore {
    loading: boolean;
    loadingDetails: boolean;
    error: string | null;
    assignments: ITripDriverAssignmentList[];
    assignmentDetails: ITripDriverAssignmentDetails | null;
    totalElements: number;
    lastUsedAssignmentParams: TripDriverAssignmentSearchParams | null;
    addTripDriverAssignmentForTrip: (assignment: ITripDriverAssignment) => Promise<void>;
    addTripDriverAssignmentForCircuit: (assignment: ITripDriverAssignment, circuitId: string) => Promise<void>;
    addTripDriverAssignmentForMultipleTrips: (assignment: ITripDriverAssignment) => Promise<void>;
    updateTripDriverAssignment: (assignment: ITripDriverAssignment) => Promise<void>;
    searchAssignments: (params?: TripDriverAssignmentSearchParams, signal?: AbortSignal) => Promise<void>;
    getAssignmentDetails: (id: string) => Promise<ITripDriverAssignmentDetails>;
    findBestDriverForTrip: (request: DriverAssignmentRequestDTO) => Promise<TripRankingResponse>;
    findBestDriverForCircuit: (request: DriverAssignmentRequestDTO) => Promise<CircuitRankingResponse>;
    findBestDriverForMultipleTrips: (request: DriverAssignmentRequestDTO & { tripIds: string[] }) => Promise<MultipleTripsRankingResponse>; 
    checkDriverAssignment: (driverId: number, startDate: string, endDate: string) => Promise<boolean>;
    searchDriversForMap: (request: DriverSearchRequestDTO) => Promise<DriverMapResponseDTO[]>;
}

export const useTripDriverAssignmentStore = create<TripDriverAssignmentStore>((set, get) => ({
    loading: false,
    loadingDetails: false,
    error: null,
    assignments: [],
    assignmentDetails: null,
    totalElements: 0,
    lastUsedAssignmentParams: null,

    addTripDriverAssignmentForTrip: async (assignment) => {
        set({ loading: true, error: null });
        try {
            await axiosInstance.post(circuitEndpoints.circuit.tripDriverAssignment.addForTrip, assignment);
            set({ loading: false });
        } catch (error: any) {
            set({
                error: error.message || "Erreur lors de l'ajout de l'affectation chauffeur-trajet",
                loading: false,
            });
            throw error;
        }
    },

    addTripDriverAssignmentForCircuit: async (assignment, circuitId) => {
        set({ loading: true, error: null });
        try {
            await axiosInstance.post(
                circuitEndpoints.circuit.tripDriverAssignment.addForCircuit, 
                assignment,
                {
                    params: { circuitId }
                }
            );
            set({ loading: false });
        } catch (error: any) {
            set({
                error: error.message || "Erreur lors de l'ajout de l'affectation chauffeur-circuit",
                loading: false,
            });
            throw error;
        }
    },
    addTripDriverAssignmentForMultipleTrips: async (assignment) => {
        set({ loading: true, error: null });
        try {
            await axiosInstance.post(
                circuitEndpoints.circuit.tripDriverAssignment.addForMultipleTrips,
                assignment
            );
            set({ loading: false });
        } catch (error: any) {
            set({
                error: error.message || "Erreur lors de l'ajout des affectations pour plusieurs trajets",
                loading: false,
            });
            throw error;
        }
    },
    updateTripDriverAssignment: async (assignment) => {
        set({ loading: true, error: null });
        try {
            await axiosInstance.post(circuitEndpoints.circuit.tripDriverAssignment.update(assignment.id), assignment);
            set({ loading: false });
        } catch (error: any) {
            set({
                error: error.message || "Erreur lors de la modification de l'affectation chauffeur-trajet",
                loading: false,
            });
            throw error;
        }
    },

    searchAssignments: async (params, externalSignal) => {
        set({ error: null, loading: true, lastUsedAssignmentParams: params });

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

            if (!externalSignal?.aborted) {
                const { content, totalElements } = response.data;
                set({
                    assignments: 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 affectations chauffeur-trajet",
                    loading: false,
                });
                throw error;
            }
        }
    },

    findBestDriverForTrip: async (request: DriverAssignmentRequestDTO) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.post<TripRankingResponse>(
                circuitEndpoints.circuit.tripDriverAssignment.findBestDriverForTrip,
                request
            );
            set({ loading: false });
            return response.data;
        } catch (error: any) {
            set({
                error: error.message || "Erreur lors de la recherche du meilleur chauffeur pour le trajet",
                loading: false,
            });
            throw error;
        }
    },

    findBestDriverForCircuit: async (request: DriverAssignmentRequestDTO) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.post<CircuitRankingResponse>(
                circuitEndpoints.circuit.tripDriverAssignment.findBestDriverForCircuit,
                request
            );
            set({ loading: false });
            return response.data;
        } catch (error: any) {
            set({
                error: error.message || "Erreur lors de la recherche du meilleur chauffeur pour le circuit",
                loading: false,
            });
            throw error;
        }
    },
    findBestDriverForMultipleTrips: async (request) => {
        set({ loading: true, error: null });
        try {
           
            const response = await axiosInstance.post<MultipleTripsRankingResponse>(
                circuitEndpoints.circuit.tripDriverAssignment.findBestDriverForMultipleTrips,
                request
            );
            set({ loading: false });
            return response.data;
        } catch (error: any) {
            set({
                error: error.message || "Erreur lors de l'optimisation IA pour plusieurs trajets",
                loading: false,
            });
            throw error;
        }
    },

    getAssignmentDetails: async (id: string) => {
        set({ loadingDetails: true, error: null });
        try {
            const response = await axiosInstance.get<ITripDriverAssignmentDetails>(circuitEndpoints.circuit.tripDriverAssignment.getAssignmentDetails(id));
            set({ loadingDetails: false, assignmentDetails: response.data });
            return response.data;
        } catch (error: any) {
            set({
                error: error.message || 'Erreur lors de la récupération des affectations chauffeur-trajet',
                loadingDetails: false,
            });
            throw error;
        }
    },

    checkDriverAssignment: async (driverId: number, startDate: string, endDate: string) => {
        set({ error: null });
        try {
            const formattedStartDate = dayjs(startDate).format('YYYY-MM-DD');
            const formattedEndDate = dayjs(endDate).format('YYYY-MM-DD');
            const response = await axiosInstance.get<boolean>(circuitEndpoints.circuit.tripDriverAssignment.checkDriverAssignment, {
                params: {
                    driverId,
                    startDate: formattedStartDate,
                    endDate: formattedEndDate
                }
            });
            return response.data;
        } catch (error: any) {
            set({
                error: error.message || 'Erreur lors de la vérification de l\'affectation du chauffeur',
            });
            throw error;
        }
    },
    searchDriversForMap: async (request: DriverSearchRequestDTO) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.post<DriverMapResponseDTO[]>(
                circuitEndpoints.circuit.tripDriverAssignment.searchDriversForMap,
                request
            );
            set({ loading: false });
            return response.data;
        } catch (error: any) {
            set({
                error: error.message || "Erreur lors de la recherche des chauffeurs pour la carte",
                loading: false,
            });
            throw error;
        }
    },
        }));
