import { create } from 'zustand';
import axiosInstance from '@/utils/axios';
import {
  IDemandeAbsence,
  LeaveType,
  LeaveStatus,
  AbsenceType,
  DemandeType,
  NotificationMode,
  ILeaveHistory
} from '@/shared/types/leave';
import { absenceEndpoints } from '../endpoints/absence';
import {
  IAbsence,
  EtatDemandeRecue,
  EtatDemandeTraitee,
  ReceivingMethod,
} from '@/shared/types/absence';
import { endpoints } from '../endpoints/absence-service';
import { mapSensToConcernedTrip } from '@/shared/types/absence';

// Match the backend's filter structure exactly
interface AgentAbsenceFilter {
  userId?: number;
  id?: string;
  submittedAt?: string;
  requestType?: 'LEAVE' | 'ABSENCE';
  startDate?: string;
  endDate?: string;
  state?: string;
  processedAt?: string;
  leaveType?: string;
  absenceType?: string;
  numberOfDays?: number;
  page?: number;
  size?: number;
  sort?: string[];
}

interface BackendAbsence {
  id: number;
  userId: number;
  user: {
    id: number;
    firstName: string;
    lastName: string;
  };
  requestType: 'LEAVE' | 'ABSENCE' | null;
  absenceType: string | null;
  leaveType: string | null;
  state: string;
  startDate: string;
  endDate: string;
  tripsIds: number[];
  observations: string;
  forecastDate: string;
  comment: string;
  receivingMethod: string;
  submittedAt: string;
  processedAt: string | null;
  numberOfDays: number;
  justificationFileUrl: string | null;
  otherLeaveDescription: string | null;
  otherAbsenceDescription: string | null;
}

interface BackendResponse {
  content: BackendAbsence[];
  totalElements: number;
  totalPages: number;
  size: number;
  number: number;
}

interface Statistics {
  leaveBalance: {
    LEAVE_MALADIE: number;
    LEAVE_PAID: number;
    LEAVE_RTT: number;
    LEAVE_SICK: number;
  };
  totals: {
    absences: number;
    total: number;
    leaves: number;
  };
  byState: {
    Unprocessed: number;
    Approved: number;
    Rejected: number;
    Waiting: number;
  };
}

const getUserIdFromStorage = (): number => {
  const userId = localStorage.getItem('userId');
  if (!userId) {
    throw new Error('User ID not found in storage');
  }
  const parsedId = parseInt(userId);
  if (isNaN(parsedId)) {
    throw new Error('Invalid user ID in storage');
  }
  return parsedId;
};

const mapBackendToFrontend = (backendAbsence: BackendAbsence): IDemandeAbsence => {
  if (!backendAbsence) {
    throw new Error('Invalid backend data');
  }

  // Map backend status to frontend status
  let status: LeaveStatus;
  switch (backendAbsence.state) {
    case 'Waiting':
    case 'Unprocessed':
      status = 'En attente';
      break;
    case 'Approved':
      status = 'Approuvée';
      break;
    case 'Rejected':
      status = 'Refusée';
      break;
    default:
      status = 'En attente';
  }

  // Determine request type
  let requestType: DemandeType;
  if (backendAbsence.requestType === 'LEAVE') {
    requestType = 'Congé';
  } else if (backendAbsence.requestType === 'ABSENCE') {
    requestType = 'Absence';
  } else {
    requestType = backendAbsence.leaveType ? 'Congé' : 'Absence';
  }

  // Map backend leave type to enum
  let leaveType: LeaveType | '' = '';
  if (backendAbsence.leaveType) {
    switch (backendAbsence.leaveType) {
      case 'LEAVE_SICK':
        leaveType = LeaveType.SICK;
        break;
      case 'LEAVE_PARENTAL':
        leaveType = LeaveType.PARENTAL;
        break;
      case 'LEAVE_PAID':
        leaveType = LeaveType.PAID;
        break;
      case 'LEAVE_UNPAID':
        leaveType = LeaveType.UNPAID;
        break;
      case 'LEAVE_RTT':
        leaveType = LeaveType.RTT;
        break;
      case 'OTHER':
        leaveType = LeaveType.OTHER;
        break;
    }
  }

  // Map backend receivingMethod to frontend notificationMode
  let notificationMode: NotificationMode = 'APPLICATION';
  switch (backendAbsence.receivingMethod) {
    case 'SMS':
      notificationMode = 'SMS';
      break;
    case 'EMAIL':
      notificationMode = 'EMAIL';
      break;
    case 'APPLICATION':
      notificationMode = 'APPLICATION';
      break;
    case 'PORTAL':
      notificationMode = 'PORTAL';
      break;
    default:
      notificationMode = 'APPLICATION';
  }

  const mappedData = {
    id: backendAbsence.id?.toString() || '',
    isActive: true,
    requestNumber: backendAbsence.id ? `REQ-${backendAbsence.id}` : '',
    submissionDate: backendAbsence.submittedAt || new Date().toISOString().split('T')[0],
    requestType,
    leaveType,
    absenceType: backendAbsence.absenceType || '',
    startDate: backendAbsence.startDate || new Date().toISOString().split('T')[0],
    endDate: backendAbsence.endDate || new Date().toISOString().split('T')[0],
    status,
    processDate: backendAbsence.processedAt || '',
    reason: backendAbsence.observations || '',
    daysCount: backendAbsence.numberOfDays || 0,
    employeeId: backendAbsence.userId?.toString() || '',
    employeeName: backendAbsence.user ? `${backendAbsence.user.firstName} ${backendAbsence.user.lastName}` : '',
    notificationMode,
    dateDebut: backendAbsence.startDate || new Date().toISOString().split('T')[0],
    dateFin: backendAbsence.endDate || new Date().toISOString().split('T')[0],
    dateSubmission: backendAbsence.submittedAt || new Date().toISOString().split('T')[0],
    dateTraitement: backendAbsence.processedAt || '',
    otherLeaveDescription: backendAbsence.otherLeaveDescription || '',
    otherAbsenceDescription: backendAbsence.otherAbsenceDescription || ''
  };

  return mappedData;
};

const mapFrontendToBackend = (frontendAbsence: IDemandeAbsence): Partial<BackendAbsence> => {
  const backendRequestType: 'LEAVE' | 'ABSENCE' =
    frontendAbsence.requestType === 'Congé' ? 'LEAVE' : 'ABSENCE';

  let backendState: string;
  switch (frontendAbsence.status) {
    case 'En attente':
      backendState = 'Waiting';
      break;
    case 'Approuvée':
      backendState = 'Approved';
      break;
    case 'Refusée':
      backendState = 'Rejected';
      break;
    default:
      backendState = 'Waiting';
  }

  // Determine if this is an HR request or employee self-request
  const isHRModule = window.location.pathname.includes('/rh/');
  
  let userId: number;
  let forEmployeeId: number | undefined;
  
  // Debug: Log current user information
  const loggedInUserId = getUserIdFromStorage();
  const loggedInUserName = localStorage.getItem('userName');
  const loggedInUserEmail = localStorage.getItem('userEmail');
  
  console.log('🔍 mapFrontendToBackend Debug:', {
    isHRModule,
    loggedInUserId,
    loggedInUserName,
    loggedInUserEmail,
    frontendEmployeeId: frontendAbsence.employeeId,
    frontendEmployeeName: frontendAbsence.employeeName
  });
  
  if (isHRModule && frontendAbsence.employeeId) {
    // HR creating/updating for an employee
    // userId = logged-in HR user (for history tracking)
    // forEmployeeId = selected employee (who the leave is for)
    userId = getUserIdFromStorage(); // WHO performed the action
    forEmployeeId = parseInt(frontendAbsence.employeeId); // WHO the leave is for
    
    if (!userId || isNaN(userId)) {
      throw new Error('HR User ID not found in storage');
    }
    if (!forEmployeeId || isNaN(forEmployeeId)) {
      throw new Error('Employee ID is required for HR requests');
    }
    
    console.log('🏢 HR Mode - Action by:', { userId: userId, userName: loggedInUserName }, 'For employee:', { forEmployeeId });
  } else if (frontendAbsence.employeeId) {
    // Employee self-request with explicit employeeId
    userId = parseInt(frontendAbsence.employeeId);
    if (!userId || isNaN(userId)) {
      throw new Error('Employee ID is required');
    }
  } else {
    // Employee self-request using logged-in user
    userId = getUserIdFromStorage();
    if (!userId) {
      throw new Error('User ID not found in storage');
    }
  }

  // Map frontend notification mode to backend receiving method
  let receivingMethod: string;
  switch (frontendAbsence.notificationMode?.toUpperCase()) {
    case 'SMS':
      receivingMethod = 'SMS';
      break;
    case 'EMAIL':
      receivingMethod = 'EMAIL';
      break;
    case 'APPLICATION':
    case 'PORTAL':
      receivingMethod = 'APPLICATION';
      break;
    default:
      receivingMethod = 'APPLICATION';
  }

  const mappedData = {
    // For HR requests: userId = HR user who performed action
    // For employee requests: userId = employee who made request
    userId: isHRModule && forEmployeeId ? forEmployeeId : userId, // WHO the leave is for
    requestType: backendRequestType,
    absenceType: backendRequestType === 'ABSENCE' ? frontendAbsence.absenceType : null,
    leaveType: backendRequestType === 'LEAVE' ? frontendAbsence.leaveType : null,
    state: backendState,
    startDate: frontendAbsence.startDate,
    endDate: frontendAbsence.endDate,
    tripsIds: [],
    observations: frontendAbsence.reason || '',
    forecastDate: frontendAbsence.startDate,
    comment: isHRModule ? `Créé par RH (User: ${loggedInUserName || loggedInUserId}, Email: ${loggedInUserEmail})` : '', // Track who performed the action
    receivingMethod: receivingMethod,
    submittedAt: new Date().toISOString().split('T')[0],
    processedAt: null,
    numberOfDays: parseInt(frontendAbsence.daysCount.toString()),
    justificationFileUrl: null,
    otherLeaveDescription: backendRequestType === 'LEAVE' && frontendAbsence.leaveType === 'OTHER' ? frontendAbsence.otherLeaveDescription : null,
    otherAbsenceDescription: backendRequestType === 'ABSENCE' && frontendAbsence.absenceType === 'OTHER' ? frontendAbsence.otherAbsenceDescription : null
  };

  console.log('📤 Sending to backend:', mappedData);
  return mappedData;
};

interface UserLeaveByYear {
  absenceType: string | null;
  totalDays: number;
  startDate: string;
  endDate: string;
}

type AbsenceStoree = {
  absences: IDemandeAbsence[];
  userAbsences: IDemandeAbsence[];
  loading: boolean;
  error: string | null;
  pagination: {
    page: number;
    size: number;
    total: number;
  };
  statistics: Statistics | null;

  searchAbsences: (
    filter: AgentAbsenceFilter,
    page: number,
    size: number,
    sort?: string[]
  ) => Promise<void>;
  getUserAbsences: (userId: number) => Promise<void>;
  getUserLeavesByYear: (userId: number, requestType: 'LEAVE' | 'ABSENCE', year: number) => Promise<UserLeaveByYear[]>;
  createAbsence: (
    absence: IDemandeAbsence,
    file?: File
  ) => Promise<{ success: boolean; data: IDemandeAbsence; message: string }>;
  updateAbsence: (
    id: string,
    absence: IDemandeAbsence,
    file?: File
  ) => Promise<{ success: boolean; data: IDemandeAbsence; message: string }>;
  setLoading: (loading: boolean) => void;
  setError: (error: string | null) => void;
  fetchStatistics: (userId?: number) => Promise<void>;
  exportAbsences: (filters?: Partial<AgentAbsenceFilter>) => Promise<{ success: boolean; message: string; exportPath?: string }>;
  exportLeaves: (filters?: { startDate?: string; endDate?: string; states?: string[] }) => Promise<{ success: boolean; message: string; filePath?: string }>;
  downloadLeaveExport: (filePath: string) => Promise<{ success: boolean; message: string }>;
  downloadExport: (filePath: string) => Promise<Blob>;
  getLeaveHistory: (leaveId: string) => Promise<{ success: boolean; data: ILeaveHistory[]; message: string }>;
};

export const useAbsenceStoree = create<AbsenceStoree>((set, get) => ({
  absences: [],
  userAbsences: [],
  loading: false,
  error: null,
  pagination: {
    page: 0,
    size: 10,
    total: 0,
  },
  statistics: null,

  setLoading: (loading: boolean) => set({ loading }),
  setError: (error: string | null) => set({ error }),

  searchAbsences: async (
    filter: AgentAbsenceFilter,
    page: number,
    size: number,
    sort?: string[]
  ) => {
    set({ loading: true, error: null });
    try {
      // For HR module, don't include userId in params if not specifically filtered
      // For employee module, always use their own userId
      const isHRModule = window.location.pathname.includes('/rh/');
      const isStaffModule = window.location.pathname.includes('/staff/');
      
      const params = {
        ...filter,
        page,
        size,
        sort: sort ? sort.join(',') : undefined,
        createdByRh: false,
      };

      // Only add requestType if:
      // 1. It's specifically provided in the filter
      // 2. OR it's not the staff module (preserve existing behavior for other modules)
      if (filter.requestType) {
        params.requestType = filter.requestType;
      } else if (!isStaffModule) {
        params.requestType = 'ABSENCE';
      }

      // Only add userId to params if:
      // 1. It's specifically provided in the filter (for HR filtering)
      // 2. OR it's the employee module (not HR) - then use logged-in user
      if (filter.userId) {
        params.userId = filter.userId;
      } else if (!isHRModule) {
        const userId = getUserIdFromStorage();
        if (!userId) {
          throw new Error('User ID not found in storage');
        }
        params.userId = userId;
      }

      const response = await axiosInstance.get<BackendResponse>(absenceEndpoints.agent.search, {
        params,
      });

      const mappedData = response.data.content.map(mapBackendToFrontend);

      set({
        absences: mappedData,
        pagination: {
          page: response.data.number,
          size: response.data.size,
          total: response.data.totalElements,
        },
        loading: false,
      });

    } catch (error: any) {
      set({ error: error.message || 'Failed to fetch absences', loading: false });
    }
  },

  getUserAbsences: async (userId: number) => {
    set({ loading: true, error: null });
    try {
      const params = {
        userId: userId,
        page: 0,
        size: 10,
      };

      const response = await axiosInstance.get<BackendResponse>(absenceEndpoints.common.search, {
        params,
      });
      set({ userAbsences: response.data.content.map(mapBackendToFrontend), loading: false });
    } catch (error: any) {
      set({ error: error.message || 'Failed to fetch user absences', loading: false });
    }
  },

  getUserLeavesByYear: async (userId: number, requestType: 'LEAVE' | 'ABSENCE', year: number) => {
    set({ loading: true, error: null });
    try {
      const response = await axiosInstance.get<UserLeaveByYear[]>(
        `/api/absence/user/${userId}/requestType/${requestType}/${year}`
      );

      set({ loading: false });
      return response.data;
    } catch (error: any) {
      set({ error: error.message || 'Failed to fetch user leaves by year', loading: false });
      return [];
    }
  },

  createAbsence: async (absence: IDemandeAbsence, file?: File) => {
    set({ loading: true, error: null });
    try {
      const backendData = mapFrontendToBackend({
        ...absence,
        id: '',
        requestNumber: '',
        processDate: '',
        dateTraitement: '',
      });

      const formData = new FormData();
      formData.append('dto', JSON.stringify(backendData));

      if (file) {
        formData.append('file', file);
      }

      const response = await axiosInstance.post<BackendAbsence>(
        absenceEndpoints.agent.create,
        formData,
        {
          headers: {
            'Content-Type': 'multipart/form-data',
          },
        }
      );

      if (response.data) {
        const mappedResponse = mapBackendToFrontend(response.data);

        set({ loading: false });

        return {
          success: true,
          data: mappedResponse,
          message: "Demande d'absence ajoutée avec succès",
        };
      }

      throw new Error('No data received from server');
    } catch (error: any) {
      set({ error: error.message || 'Failed to create absence', loading: false });
      return {
        success: false,
        data: absence,
        message: error.response?.data?.message || 'Échec de la création de la demande',
      };
    }
  },

  updateAbsence: async (id: string, absence: IDemandeAbsence, file?: File) => {
    set({ loading: true, error: null });
    try {
      const formData = new FormData();
      const backendData = mapFrontendToBackend(absence);
      formData.append('dto', JSON.stringify(backendData));

      if (file) {
        formData.append('file', file);
      }

      const response = await axiosInstance.put<BackendAbsence>(
        absenceEndpoints.agent.update(id),
        formData,
        {
          headers: {
            'Content-Type': 'multipart/form-data',
          },
        }
      );

      if (response.data) {
        const mappedResponse = mapBackendToFrontend(response.data);

        set({ loading: false });
        return {
          success: true,
          data: mappedResponse,
          message: "Demande d'absence mise à jour avec succès",
        };
      }

      throw new Error('No data received from server');
    } catch (error: any) {
      set({ error: error.message || 'Failed to update absence', loading: false });
      return {
        success: false,
        data: absence,
        message: error.response?.data?.message || 'Échec de la mise à jour de la demande',
      };
    }
  },

  fetchStatistics: async (userId?: number) => {
    set({ loading: true, error: null });
    try {
      const effectiveUserId = userId || getUserIdFromStorage();
      if (!effectiveUserId) {
        throw new Error('User ID not found');
      }

      const response = await axiosInstance.get<Statistics>(
        absenceEndpoints.agent.statistics(effectiveUserId)
      );

      set({
        statistics: response.data,
        loading: false,
      });
    } catch (error: any) {
      set({
        error: error.message || 'Failed to fetch statistics',
        loading: false,
      });
    }
  },

  exportAbsences: async (filters?: Partial<AgentAbsenceFilter>) => {
    set({ loading: true, error: null });
    try {
      const userId = getUserIdFromStorage();
      if (!userId) {
        throw new Error('User ID not found in storage');
      }

      // Prepare parameters according to your backend controller
      const params = new URLSearchParams();
      
      // CRITICAL: Always exclude RH-created absences in agent module
      params.append('createdByRh', 'false');
      
      // Use the requestType from filters or default to ABSENCE
      params.append('requestType', filters?.requestType || 'ABSENCE');
      params.append('userId', userId.toString());
      
      // Add other filters if provided
      if (filters?.state) params.append('states', filters.state);
      if (filters?.startDate) params.append('startDate', filters.startDate);
      if (filters?.endDate) params.append('endDate', filters.endDate);
      if (filters?.absenceType) params.append('absenceTypes', filters.absenceType);
      if (filters?.leaveType) params.append('functionTypes', filters.leaveType);

      const response = await axiosInstance.post<{ ExportPath: string }>(
        absenceEndpoints.agent.exportAbsences,
        null,
        { params }
      );

      if (response.data && response.data.ExportPath) {
        set({ loading: false });
        return {
          success: true,
          message: 'Export des absences agents terminé avec succès',
          exportPath: response.data.ExportPath,
        };
      }

      throw new Error('No export path received from server');
    } catch (error: any) {
      set({
        error: error.message || 'Failed to export absences',
        loading: false,
      });
      return {
        success: false,
        message: error.response?.data?.message || 'Échec de l\'exportation des absences agents',
      };
    }
  },

  exportLeaves: async (filters?: { startDate?: string; endDate?: string; states?: string[] }) => {
    set({ loading: true, error: null });
    try {
      const userId = getUserIdFromStorage();
      if (!userId) {
        throw new Error('User ID not found in storage');
      }

      // Prepare request body according to your controller
      const requestBody = {
        userId: userId,
        userIds: [userId], // Include both for flexibility
        states: filters?.states || [],
        startDate: filters?.startDate ? new Date(filters.startDate).toISOString() : null,
        endDate: filters?.endDate ? new Date(filters.endDate).toISOString() : null,
        requestType: 'LEAVE' // Specify LEAVE type for conge
      };

      const response = await axiosInstance.post<{ filePath: string }>(
        absenceEndpoints.agent.exportAbsences, // Using endpoint from absence.ts
        requestBody
      );

      if (response.data && response.data.filePath) {
        set({ loading: false });
        return {
          success: true,
          message: 'Export des congés terminé avec succès',
          filePath: response.data.filePath,
        };
      }

      throw new Error('No file path received from server');
    } catch (error: any) {
      set({
        error: error.message || 'Failed to export leaves',
        loading: false,
      });
      return {
        success: false,
        message: error.response?.data?.message || 'Échec de l\'exportation des congés',
      };
    }
  },

  downloadLeaveExport: async (filePath: string) => {
    set({ loading: true, error: null });
    try {
      const response = await axiosInstance.get(
        `${absenceEndpoints.agent.downloadExport}?filePath=${encodeURIComponent(filePath)}`, // Using endpoint from absence.ts
        {
          responseType: 'blob',
        }
      );

      if (response.data) {
        // Create download link
        const url = window.URL.createObjectURL(new Blob([response.data]));
        const link = document.createElement('a');
        link.href = url;
        
        // Extract filename from filePath
        const fileName = filePath.substring(filePath.lastIndexOf('/') + 1) || 'export_conges.xlsx';
        link.setAttribute('download', fileName);
        
        document.body.appendChild(link);
        link.click();
        link.remove();
        window.URL.revokeObjectURL(url);

        set({ loading: false });
        return {
          success: true,
          message: 'Téléchargement terminé avec succès',
        };
      }

      throw new Error('No data received from server');
    } catch (error: any) {
      set({
        error: error.message || 'Failed to download export',
        loading: false,
      });
      return {
        success: false,
        message: error.response?.data?.message || 'Échec du téléchargement',
      };
    }
  },

  downloadExport: async (filePath: string) => {
    set({ loading: true, error: null });
    try {
      const response = await axiosInstance.get(
        `${absenceEndpoints.agent.downloadExport}?filePath=${encodeURIComponent(filePath)}`,
        {
          responseType: 'blob',
        }
      );

      if (response.data) {
        set({ loading: false });
        return response.data;
      }

      throw new Error('No data received from server');
    } catch (error: any) {
      set({
        error: error.message || 'Failed to download export',
        loading: false,
      });
      throw error;
    }
  },

  getLeaveHistory: async (leaveId: string) => {
    set({ loading: true, error: null });
    try {
      const response = await axiosInstance.get<ILeaveHistory[]>(
        absenceEndpoints.agent.history(leaveId)
      );

      set({ loading: false });
      
      return {
        success: true,
        data: response.data,
        message: 'Historique récupéré avec succès'
      };
    } catch (error: any) {
      console.error('Error in getLeaveHistory:', error);
      set({ 
        error: error.message || 'Failed to fetch history', 
        loading: false 
      });
      return {
        success: false,
        data: [],
        message: error.response?.data?.message || 'Échec de la récupération de l\'historique'
      };
    }
  },
}));

interface AbsencePageFilterParams {
  page?: number;
  size?: number;
  sortBy?: string;
  sortDirection?: 'asc' | 'desc';
  state?: string[];
  passengerId?: number;
  receivingMethod?: string;
  establishment?: string;
  departmentName?: string;
  lastName?: string;
  firstName?: string;
  startDate?: string;
  endDate?: string;
}

interface PassengerResponse {
  content: Array<{
    id: number;
    firstName: string;
    lastName: string;
    establishmentName: string;
    departmentName: string;
  }>;
}

interface ExportFilters {
  firstName?: string;
  lastName?: string;
  state?: string;
  startDate?: string;
  endDate?: string;
  reportedBy?: string;
  userId?: string;
}

// Map frontend state to backend state
const mapEtatToBackendState = (etat: string): string => {
  switch (etat) {
    case 'En cours':
      return 'In_progress';
    case 'Non traité':
      return 'Unprocessed';
    case 'Annulé':
      return 'Cancelled';
    case 'Traité':
      return 'Processed';
    default:
      return 'Unprocessed';
  }
};

type AbsenceStore = {
  loading: boolean;
  error: string | null;
  unprocessedAbsences: IAbsence[];
  processedAbsences: IAbsence[];
  unprocessedTotalElements: number;
  processedTotalElements: number;
  passengers: {
    id: number;
    value: string;
    label: string;
    establishmentName: string;
    departmentName: string;
  }[];
  maxAbsencesCount: number;
  fetchMaxAbsencesCount: () => Promise<void>;
  fetchUnprocessedAbsences: (params?: AbsencePageFilterParams) => Promise<void>;
  fetchProcessedAbsences: (params?: AbsencePageFilterParams) => Promise<void>;
  fetchPassengers: () => Promise<void>;
  absences: IAbsence[];
  fetchAbsences: () => Promise<void>;
  absenceById: IAbsence | null;
  getAbsenceById: (id: string) => Promise<IAbsence>;
  updateAbsence: (id: number, absence: Partial<IAbsence>) => Promise<void>;
  createAbsence: (createData: any) => Promise<IAbsence>;
  startExportAbsences: (params?: any) => Promise<any>;
  exportLeaves: (filters?: { startDate?: string; endDate?: string; states?: string[] }) => Promise<{ success: boolean; message: string; filePath?: string }>;
  downloadLeaveExport: (filePath: string) => Promise<{ success: boolean; message: string }>;
};

export const useAbsenceStore = create<AbsenceStore>((set, get) => ({
  loading: false,
  error: null,
  unprocessedAbsences: [],
  processedAbsences: [],
  unprocessedTotalElements: 0,
  processedTotalElements: 0,
  maxAbsencesCount: 1000,
  passengers: [],
  fetchPassengers: async () => {
    try {
      const response = await axiosInstance.get<PassengerResponse>(endpoints.User.searchPassengers);
      set((state) => ({
        ...state,
        passengers: response.data.content.map((passenger) => ({
          id: passenger.id,
          value: passenger.id.toString(),
          label: `${passenger.firstName} ${passenger.lastName}`,
          establishmentName: passenger.establishmentName,
          departmentName: passenger.departmentName,
        })),
      }));
    } catch (error) {
      console.error('Failed to fetch passengers:', error);
    }
  },
  fetchUnprocessedAbsences: async (params?: AbsencePageFilterParams) => {
    set({ loading: true, error: null });
    try {
      const response = await axiosInstance.get(endpoints.Absence.getAbsences, {
        params: {
          ...params,
          state: ['Unprocessed', 'In_progress'],
        },
        paramsSerializer: {
          indexes: null,
        },
      });
      set({
        unprocessedAbsences: response.data.content,
        unprocessedTotalElements: response.data.totalElements,
        loading: false,
      });
    
    } catch (error: any) {
      set({
        error: error.message || 'Failed to fetch unprocessed absences',
        loading: false,
      });
    }
  },
  fetchProcessedAbsences: async (params?: AbsencePageFilterParams) => {
    set({ loading: true, error: null });
    try {
      const response = await axiosInstance.get(endpoints.Absence.getAbsences, {
        params: {
          ...params,
          state: ['Processed', 'Cancelled'],
        },
        paramsSerializer: {
          indexes: null,
        },
      });
      set({
        processedAbsences: response.data.content,
        processedTotalElements: response.data.totalElements,
        loading: false,
      });
    } catch (error: any) {
      set({
        error: error.message || 'Failed to fetch processed absences',
        loading: false,
      });
    }
  },
  absences: [],
  fetchAbsences: async () => {
    set({ loading: true, error: null });
    try {
      const response = await axiosInstance.get(endpoints.Absence.getAbsences);
      set({
        absences: response.data.content,
        loading: false,
      });
    } catch (error: any) {
      set({
        error: error.message || 'Failed to fetch absences',
        loading: false,
      });
    }
  },
  absenceById: null,
  getAbsenceById: async (id: string) => {
    set({ loading: true, error: null });
    try {
      const response = await axiosInstance.get(endpoints.Absence.getAbsenceById(id));
      set({
        absenceById: response.data,
        loading: false,
      });
      return response.data;
    } catch (error: any) {
      set({
        error: error.message || 'Failed to get absence by id',
        loading: false,
      });
    }
  },
  updateAbsence: async (id: number, absence: Partial<IAbsence>) => {
    set({ loading: true, error: null });
    try {
      await axiosInstance.put(endpoints.Absence.updateAbsence(id), absence);

      await Promise.all([get().fetchUnprocessedAbsences(), get().fetchProcessedAbsences()]);

      set({ loading: false });
    } catch (error: any) {
      set({
        error: error.message || 'Failed to update absence',
        loading: false,
      });
      throw error;
    }
  },
  createAbsence: async (createData: any) => {
    set({ loading: true, error: null });
    try {
      const response = await axiosInstance.post(endpoints.Absence.createAbsence, createData);
      await Promise.all([get().fetchUnprocessedAbsences(), get().fetchProcessedAbsences()]);

      set({ loading: false });
      return response.data;
    } catch (error: any) {
      console.error('Error creating absence:', error); // Debug log
      set({
        error: error.message || 'Failed to create absence',
        loading: false,
      });
      throw error;
    }
  },
  startExportAbsences: async (params?: any) => {
    set({ loading: true, error: null });
    try {
      const response = await axiosInstance.post(endpoints.Absence.exportAbsence, { params });
      set({ loading: false });
      return response.data;
    } catch (error: any) {
      set({
        error: error.message || 'Failed to start export absences',
        loading: false,
      });
      throw error;
    }
  },

  exportLeaves: async (filters?: { startDate?: string; endDate?: string; states?: string[] }) => {
    set({ loading: true, error: null });
    try {
      const userId = getUserIdFromStorage();
      if (!userId) {
        throw new Error('User ID not found in storage');
      }

      // Prepare request body according to your controller
      const requestBody = {
        userId: userId,
        userIds: [userId], // Include both for flexibility
        states: filters?.states || [],
        startDate: filters?.startDate ? new Date(filters.startDate).toISOString() : null,
        endDate: filters?.endDate ? new Date(filters.endDate).toISOString() : null,
        requestType: 'LEAVE' // Specify LEAVE type for conge
      };

      const response = await axiosInstance.post<{ filePath: string }>(
        absenceEndpoints.agent.exportAbsences, // Using your controller path
        requestBody
      );

      if (response.data && response.data.filePath) {
        set({ loading: false });
        return {
          success: true,
          message: 'Export des congés terminé avec succès',
          filePath: response.data.filePath,
        };
      }

      throw new Error('No file path received from server');
    } catch (error: any) {
      set({
        error: error.message || 'Failed to export leaves',
        loading: false,
      });
      return {
        success: false,
        message: error.response?.data?.message || 'Échec de l\'exportation des congés',
      };
    }
  },

  downloadLeaveExport: async (filePath: string) => {
    set({ loading: true, error: null });
    try {
      const response = await axiosInstance.get(
        `${absenceEndpoints.agent.downloadExport}?filePath=${encodeURIComponent(filePath)}`,
        {
          responseType: 'blob',
        }
      );

      if (response.data) {
        // Create download link
        const url = window.URL.createObjectURL(new Blob([response.data]));
        const link = document.createElement('a');
        link.href = url;
        
        // Extract filename from filePath
        const fileName = filePath.substring(filePath.lastIndexOf('/') + 1) || 'export_conges.xlsx';
        link.setAttribute('download', fileName);
        
        document.body.appendChild(link);
        link.click();
        link.remove();
        window.URL.revokeObjectURL(url);

        set({ loading: false });
        return {
          success: true,
          message: 'Téléchargement terminé avec succès',
        };
      }

      throw new Error('No data received from server');
    } catch (error: any) {
      set({
        error: error.message || 'Failed to download export',
        loading: false,
      });
      return {
        success: false,
        message: error.response?.data?.message || 'Échec du téléchargement',
      };
    }
  },

  fetchMaxAbsencesCount: async () => {
    try {
      const response = await axiosInstance.get<number>(endpoints.Absence.countAbsences);
      set({ maxAbsencesCount: response.data });
    } catch (error) {
      console.error('Failed to fetch max absences count:', error);
      set({ maxAbsencesCount: 1000 });
    }
  },
}));


