import axiosInstance from "@/utils/axios";
import { create } from "zustand";
import { driverAbsenceEndpoints } from "../endpoints/driverAbsence";
import { IDriverType } from "@/shared/types/driver";
import { DriverAbsence } from "@/shared/sections/chauffeur/planingChauffeur/types";

export interface DriverAbsenceList {
  id: number;
  createdAt: string;
  updatedAt: string;
  driverName: string;
  driver: IDriverType;
  absenceType: string;
  startDate: string;
  endDate: string;
  isAssigned: boolean;
  status: DriverAbsenceStatut;
  nbHours: number | null;
  supportingDocumentId: number;
  receptionMode: string;
  validatedBy: number | null;
  authorizedBy: number | null;
  observations: string;
  ownerUUid?: string;
  validatedByName?: string | null;
  authorizedByName?: string | null;
}

export enum DriverAbsenceStatut {
  INVALID = "INVALID",
  IN_PROGRESS = "IN_PROGRESS",
  ACCEPTED = "ACCEPTED",
  REJECTED = "REJECTED",
}

interface Paginated<T> {
  content: T[];
  pageable: { pageNumber: number; pageSize: number };
  totalElements: number;
  totalPages: number;
}

export type Search = {
  page?: number;
  size?: number,
  absenceId?: number,
  status?: string,
  absenceType?: string,
  receptionMode?: string,
  nbHours?: number,
  authorizedByName?: string,
  validatedByName?: string,
  driverName?: string,
  driverId?: string,
  isAssigned?: boolean | null,
  driverTraject?: boolean | null
  startDate?: string | null;
  endDate?: string | null;
  sortField?: string;
  sortDirection?: string;
};

export enum DriverAbsenceType {
  AUTHORIZED_ABSENCE = "AUTHORIZED_ABSENCE",
  UNAUTHORIZED_ABSENCE = "UNAUTHORIZED_ABSENCE",
  EXCEPTIONAL_REMOTE_WORK = "EXCEPTIONAL_REMOTE_WORK",
  EXTERNAL_ASSIGNMENT = "EXTERNAL_ASSIGNMENT",
  MEDICAL_APPOINTMENT = "MEDICAL_APPOINTMENT",
  PROFESSIONAL_TRAINING = "FORMATION_PROFESSIONNELLE",
  OTHER = "AUTRE"
}

export enum ReceptionMode {
  MAIL = "MAIL",
  SMS = "SMS",
  PORTAL = "PORTAL",
}

export interface DriverAbsenceRequest {
  driverId: number;
  driverName: string;
  absenceType: string;
  startDate: Date;
  endDate: Date;
  nbHours: number;
  supportingDocumentId: number;
  receptionMode: string;
  observations?: string | null;
  driverTraject: boolean;
  isAssigned: boolean;
  status: string;
  validatedBy?: number | null;
  authorizedBy?: number | null;
}

type Store = {
  processed: DriverAbsenceList[];
  unprocessed: DriverAbsenceList[];
  processedTotal: number;
  unprocessedTotal: number;
  processedLoading: boolean;
  unprocessedLoading: boolean;
  fetchProcessed: (p: Search) => Promise<void>;
  fetchUnprocessed: (p: Search) => Promise<void>;
  createAbsence: (p: DriverAbsenceRequest) => Promise<void>;
  updateAbsence: (id: string, p: DriverAbsenceRequest) => Promise<void>;
  getAbsenceById: (id: number) => Promise<DriverAbsenceList>;
  changeAbsenceStatus: (id: number, status: string, userId: number) => Promise<void>;
  findAbsencesForDriverPlanning: (date: string) => Promise<DriverAbsence[]>;
};

export const useDriverAbsenceStore = create<Store>(set => ({
  processed: [],
  unprocessed: [],
  processedTotal: 0,
  unprocessedTotal: 0,
  processedLoading: false,
  unprocessedLoading: false,

  fetchProcessed: async params => {
    set({ processedLoading: true });
    const { data } = await axiosInstance.get<Paginated<DriverAbsenceList>>(
      driverAbsenceEndpoints.General.getProcessed,
      { params },
    );
    set({ processed: data.content, processedTotal: data.totalElements, processedLoading: false });
  },

  fetchUnprocessed: async params => {
    set({ unprocessedLoading: true });
    const { data } = await axiosInstance.get<Paginated<DriverAbsenceList>>(
      driverAbsenceEndpoints.General.getUnprocessed,
      { params },
    );
    set({ unprocessed: data.content, unprocessedTotal: data.totalElements, unprocessedLoading: false });
  },
  createAbsence: async payload => {
    set({ processedLoading: true, unprocessedLoading: true });
    try {
      const { data } = await axiosInstance.post<DriverAbsenceList>(
        driverAbsenceEndpoints.Create.create,
        { ...payload, ownerUUid: localStorage.getItem('userUuid') || '' }
      );

      set(s => {
        const addTo = data.status === "IN_PROGRESS" || data.status === "INVALID"
          ? { unprocessed: [...s.unprocessed, data] }
          : { processed: [...s.processed, data] };

        return {
          ...addTo,
          processedLoading: false,
          unprocessedLoading: false,
        };
      });
    } catch (e: any) {
      set({ processedLoading: false, unprocessedLoading: false });
      throw e;
    }
  },
  updateAbsence: async (id: string, payload: DriverAbsenceRequest) => {
    set({ processedLoading: true, unprocessedLoading: true });
    try {
      const { data } = await axiosInstance.put<DriverAbsenceList>(
        driverAbsenceEndpoints.Update.update(id),
        { ...payload, ownerUUid: localStorage.getItem('userUuid') || '' }
      );
      set((state) => {
        const updatedUnprocessed = state.unprocessed.map((item) =>
          item.id === data.id ? data : item
        );

        const updatedProcessed = state.processed.map((item) =>
          item.id === data.id ? data : item
        );

        const addTo = data.status === "IN_PROGRESS" || data.status === "INVALID"
          ? { unprocessed: updatedUnprocessed }
          : { processed: updatedProcessed };

        return {
          ...addTo,
          processedLoading: false,
          unprocessedLoading: false,
        };
      });
    } catch (e: any) {
      set({ processedLoading: false, unprocessedLoading: false });
      throw e;
    }
  },
  getAbsenceById: async (id: number) => {
    const { data } = await axiosInstance.get<DriverAbsenceList>(
      driverAbsenceEndpoints.General.getById(id)
    );
    return data;
  }
  ,
  changeAbsenceStatus: async (id: number, status: string, userId: number) => {
    set({ processedLoading: true, unprocessedLoading: true });
    try {
      const { data } = await axiosInstance.put<DriverAbsenceList>(
        driverAbsenceEndpoints.Status.changeStatus(id, status, userId)
      );

      // Remove the item from both lists first
      set((state) => ({
        ...state,
        unprocessed: state.unprocessed.filter(item => item.id !== data.id),
        processed: state.processed.filter(item => item.id !== data.id),
        processedLoading: false,
        unprocessedLoading: false,
      }));

      // Then add it to the appropriate list based on status
      set((state) => {
        const isProcessed = data.status === "ACCEPTED" || data.status === "REJECTED";

        if (isProcessed) {
          return {
            ...state,
            processed: [...state.processed, data],
          };
        } else {
          return {
            ...state,
            unprocessed: [...state.unprocessed, data],
          };
        }
      });
    } catch (e: any) {
      set({ processedLoading: false, unprocessedLoading: false });
      throw e;
    }
  },
  findAbsencesForDriverPlanning: async (date: string) => {
    try {
      const { data } = await axiosInstance.get<DriverAbsence[]>(
        driverAbsenceEndpoints.General.findAbsencesForDriverPlanning(date)
      );
      
      return data;
    } catch (e: any) {
      throw e;
    }
  }
}));
