import axiosInstance from "@/utils/axios";
import { create } from "zustand";
import { userEndpoints } from "../endpoints/user";
import { Representative, PassengerNameDTO } from "@/shared/types/passenger";
import { IPassengerList, SearchPassengerParams, State } from "@/shared/types/passenger";

type PassengerStore = {
    passengers: IPassengerList[];
    passenger: IPassengerList | null;
    loading: boolean;
    error: string | null;
    totalElements: number;
    lastUsedPassengerParams: SearchPassengerParams | null;
    searchPassengers: (params?: SearchPassengerParams, signal?: AbortSignal) => Promise<void>;
    addPassenger: (passenger: IPassengerList) => Promise<IPassengerList>;
    updatePassenger: (passenger: IPassengerList) => Promise<void>;
    toggleArchive: (id: string) => Promise<void>;
    exportPassengers: (params: SearchPassengerParams & { userId: number }) => Promise<string | null>;
    getShortPassengers: (params?: SearchPassengerParams) => Promise<void>;
    getPassengerById: (id: string) => Promise<IPassengerList>;
    updatePassengerStatus: (id: string, passengerState: State) => Promise<void>;
    searchPassengerNames: (keyword?: string) => Promise<PassengerNameDTO[]>;
    loadingRepresentatives: boolean;
    downloadPassengersTemplate: () => Promise<void>;
    importPassengers: (file: File) => Promise<void>;
    exportingPassengersTemplateLoader: boolean;
};

export const usePassengerStore = create<PassengerStore>((set, get) => ({
    passengers: [],
    passenger: null,
    loading: false,
    error: null,
    totalElements: 0,
    lastUsedPassengerParams: null,
    loadingRepresentatives: false,
    exportingPassengersTemplateLoader: false,
    searchPassengers: async (params, externalSignal) => {
        set({ error: null, loading: true, lastUsedPassengerParams: params })

        try {
            const response = await axiosInstance.get(userEndpoints.user.passenger.getAllPassengers, {
                params,
                signal: externalSignal,
            })

            if (!externalSignal?.aborted) {
                const { content, totalElements } = response.data
                set({
                    passengers: content,
                    totalElements,
                    loading: false,
                })
            }
        } catch (error: any) {
            if (error.name !== "CanceledError" && error.code !== "ERR_CANCELED") {
                set({
                    error: error.message || "Failed to search passengers",
                    loading: false,
                })
                throw error
            }
        }
    },

    downloadPassengersTemplate: async () => {
        try {
            set({ exportingPassengersTemplateLoader: true });
            const response = await axiosInstance.get(userEndpoints.user.passenger.downloadPassengersTemplate, {
                responseType: 'blob',
            });

            const contentDisposition = response.headers['content-disposition'] as string | undefined;
            let filename = 'template_passengers.xlsx';
            if (contentDisposition) {
                const match = contentDisposition.match(/filename\*=UTF-8''([^;]+)|filename="?([^";]+)"?/i);
                const extracted = match?.[1] || match?.[2];
                if (extracted) filename = decodeURIComponent(extracted);
            }

            const blob = new Blob([response.data], { type: 'application/octet-stream' });
            const url = window.URL.createObjectURL(blob);
            const link = document.createElement('a');
            link.href = url;
            link.setAttribute('download', filename);
            document.body.appendChild(link);
            link.click();
            link.remove();
            window.URL.revokeObjectURL(url);
        } catch (error: any) {
            throw error;
        } finally {
            set({ exportingPassengersTemplateLoader: false });
        }
    },

    importPassengers: async (file: File) => {
        try {
            const formData = new FormData();
            formData.append('file', file);

            const userId = typeof window !== 'undefined' ? localStorage.getItem('userId') : null;
            if (userId) formData.append('uploadedBy', userId);

            await axiosInstance.post(userEndpoints.user.passenger.importPassengers, formData, {
                headers: { 'Content-Type': 'multipart/form-data' },
            });
        } catch (error: any) {
            throw error;
        }
    },

    addPassenger: async (passenger: IPassengerList) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.post(userEndpoints.user.passenger.addPassenger, passenger);
            const { lastUsedPassengerParams, searchPassengers } = get();
            if (lastUsedPassengerParams) {
                await searchPassengers(lastUsedPassengerParams);
            }
            set({ loading: false });
            return response.data;
            } catch (error: any) {
            set({
                error: error.message || 'Failed to add passenger',
                loading: false,
            });
            throw error
        }
    },

    updatePassenger: async (passenger) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.post(userEndpoints.user.passenger.updatePassenger, passenger);
            set((state) => ({
                passengers: state.passengers.map((c) => (c.id === passenger.id ? passenger : c)),
                loading: false,
            }));
        } catch (error: any) {
            set({
                error: error.message || 'Failed to update passenger',
                loading: false,
            });
            throw error
        }
    },

    toggleArchive: async (id: string) => {
        set({ loading: true, error: null });
        try {
            await axiosInstance.post<boolean>(userEndpoints.user.passenger.toggleArchive(id));
            set((state) => ({
                passengers: state.passengers.map((c) => (c.id === id ? { ...c, archived: !c.archived } : c)),
                loading: false,
            }));
        } catch (error: any) {
            set({
                error: error.message || 'Failed to toggle archive',
                loading: false,
            });
            throw error;
        }
    },
    exportPassengers: async (params) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.post<{ ExportPath: string }>(
                userEndpoints.user.passenger.exportPassengers,
                null,
                { params }
            );

            return response.data.ExportPath;
        } catch (error: any) {
            set({ error: error.message || 'Échec de l’export des usagers', loading: false });
            throw error;
        } finally {
            set({ loading: false });
        }
    },

    getShortPassengers: async (params?: SearchPassengerParams) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.get(userEndpoints.user.passenger.getShortPassengers, {
                params,
            });
            set({
                passengers: response.data.content,
                loading: false,
            });
        } catch (error: any) {
            set({
                error: error.message || 'Failed to fetch short passengers',
                loading: false,
            });
            throw error;
        }
    },

    getPassengerById: async (id: string) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.get<IPassengerList>(userEndpoints.user.passenger.getPassengerById(id));
            set({
                passenger: response.data,
                loading: false
            });
            return response.data;
        } catch (error: any) {
            set({
                error: error.message || 'Failed to fetch passenger by ID',
                loading: false,
            });
            throw error;
        }
    },
    updatePassengerStatus: async (id, passengerState) => {
        set({ loading: true, error: null });
        try {
            await axiosInstance.put<State>(
            userEndpoints.user.passenger.updateStatus(id, passengerState)
            );
            set((state) => ({
                passengers: state.passengers.map((c) => (c.id === id ? { ...c, state: passengerState } : c)),
                loading: false,
            }));
        } catch (error: any) {
            set({
                error: error.message || 'Failed to update circuit status',
                loading: false,
            });
            throw error;
        }
    },
    searchPassengerNames: async (keyword) => {
        set({ loading: true, error: null });
        try {
            const response = await axiosInstance.get<PassengerNameDTO[]>(
                userEndpoints.user.passenger.searchPassengerNames,
                { params: { keyword } }
            );
            set({ loading: false, error: null });
            return response.data;
        } catch (error: any) {
            set({
                error: error.message || 'Failed to search passenger names',
                loading: false
            });
            return [];
        }
    }
}));
