import { create } from 'zustand';
import { roadMapEndpoints } from '../endpoints/roadMap';

import axiosInstance from '@/utils/axios';
import {
  IOldRoadmap,
  IValidRoadmap,
  OldSubmittedRoadMapFilterParams,
  ValidRoadmapFilterParams,
} from '@/shared/types/driver';
import { ManualRoadMapCreationResult } from '@/shared/sections/chauffeur/roadmap/components/roadmap-list/invalid-roadmap-dialog';
import {
  IRoadmap,
  ICombinedTable,
  IDriverRoadmap,
  IGeolocationData,
  PlanningData,
  RoadMapPageFilterParams,
  SubmittedRoadMapDTO,
  ValidatedRoadMapTable,
  DriverRoadMapDetailsDTO,
  IRoadMapStatistics,
  OldRoadMapByDriverFilterParams,
  RoadMapStatus,
  SubmittedRoadMapFilterParams,
  SchedulePlanningPayload,
  PlanningRequestFilterParams,
  PlanningRequest,
  PlanningRequestDetails,
} from '@/shared/types/roadMap';
import { PlanningDriverFilterParams } from './planningDriverStore';

type RoadMapStore = {
  validatedRoadMap: IRoadmap[];
  roadMapStatistics: IRoadMapStatistics | null;
  dealvalidatedRoadMap: IValidRoadmap[];
  submittedRoadMaps: SubmittedRoadMapDTO[];
  oldSubmittedRoadMaps: IOldRoadmap[];
  validatedRoadMapDetails: ValidatedRoadMapTable | null;
  updatedValidRoadmapStatus: null;
  geolocData: IGeolocationData | null;
  planningData: PlanningData | null;
  driverRoadMapDetails: IDriverRoadmap | null;
  combinedTable: ICombinedTable | null;
  loading: boolean;
  error: string | null;
  planningRequests: PlanningRequest[];
  workedDaysDates: string[];
  getAllValidRoadMap: (params?: RoadMapPageFilterParams) => Promise<void>;
  getAllSubmittedRoadMaps: (params?: SubmittedRoadMapFilterParams) => Promise<void>;
  getOldSubmittedRoadMaps: (params: OldSubmittedRoadMapFilterParams) => Promise<void>;
  oldSubmittedRoadMapDetails: DriverRoadMapDetailsDTO | null;
  getOldSubmittedRoadMapDetails: (id: number) => Promise<void>;
  oldValidattedRoadMapDetails: DriverRoadMapDetailsDTO | null;
  getOldValidattedRoadMapDetails: (id: number) => Promise<void>;
  totalElements: number;
  createValidatedRoadMapsManually: (payload: {
    driverIds: number[];
    date: string;
  }) => Promise<ManualRoadMapCreationResult>;
  getOldRoadMapByDriver: (params?: OldRoadMapByDriverFilterParams) => Promise<void>;
  getAllDealValidRoadMap: (params?: ValidRoadmapFilterParams) => Promise<void>;
  getRoadMapStatistics: () => Promise<void>;
  createRoadMapsManually: (payload: {
    driverIds: number[];
    date: string;
  }) => Promise<ManualRoadMapCreationResult>;
  updateRoadMapStatus: (id: number, newStatus: string) => Promise<void>;
  getValidedRoadmap: (id: number) => Promise<void>;
  updateValidRoadmapStatus: (id: number) => Promise<void>;
  getGeolocData: (driverId: number, year: number, month: number) => Promise<void>;
  getPlanningData: (driverId: string, date: string) => Promise<void>;
  getDriverRoadMap: (driverId: string, date: string) => Promise<void>;
  getCombinedTable: (driverId: number, date: string) => Promise<void>;
  createOrUpdateDailyRoadMap: (
    validatedRoadMapId: number,
    combinedTableDayId: number,
    date: string,
    payload: {
      startHour: string | null;
      endHour: string | null;
      type: string;
    }[]
  ) => Promise<void>;
  updateSubmittedRoadMapStatus: (id: number, isSubmitted: boolean) => Promise<void>;
  schedulePlanning: (planningRequest: SchedulePlanningPayload) => Promise<void>;
  getAllPlanningRequest: (params?: PlanningRequestFilterParams) => Promise<void>;
  planningRequestDetails: PlanningRequestDetails[];
  getPlanningRequestDetails: (requestId: number) => Promise<void>;
  getWorkedDaysDates: (roadMapId: number ) => Promise<void>;

};

export const useRoadMapStore = create<RoadMapStore>((set) => ({
  validatedRoadMap: [],
  roadMapStatistics: null,
  dealvalidatedRoadMap: [],
  submittedRoadMaps: [],
  oldSubmittedRoadMaps: [],
  oldSubmittedRoadMapDetails: null,
  oldValidattedRoadMapDetails: null,
  validatedRoadMapDetails: null,
  updatedValidRoadmapStatus: null,
  geolocData: null,
  planningData: null,
  driverRoadMapDetails: null,
  combinedTable: null,
  loading: false,
  error: null,
  totalElements: 0,
  planningRequests: [],
  planningRequestDetails: [],
  workedDaysDates: [],

  getAllValidRoadMap: async (params = { status }) => {
    set({ loading: true, error: null });
    try {
      const response = await axiosInstance.get(
        roadMapEndpoints.roadMap.validaRoadMap.getAllValidRoadmap,
        { params }
      );
      const { content, totalElements } = response.data;
      set({ validatedRoadMap: content,totalElements: totalElements,loading: false });
    } catch (error: any) {
      set({ error: error.message || 'Failed to fetch validatedRoadMap', loading: false });
    }
  },

  getAllSubmittedRoadMaps: async (params = {}) => {
    set({ loading: true, error: null });
    try {
      const response = await axiosInstance.get(
        roadMapEndpoints.roadMap.submittedRoadMap.getAllsubmittedRoadmap,
        { params }
      );
      const { content, totalElements } = response.data;
      set({ submittedRoadMaps: content, loading: false, totalElements });
    } catch (error: any) {
      set({ error: error.message || 'Failed to fetch submittedRoadMaps', loading: false });
    }
  },

  getOldSubmittedRoadMaps: async (params) => {
    set({ loading: true, error: null });
    try {
      const response = await axiosInstance.get(
        roadMapEndpoints.roadMap.submittedRoadMap.getOldSubmittedRoadmaps,
        { params }
      );
      const { content, totalElements } = response.data;

      const mappedContent: IOldRoadmap[] = content.map((item: any) => ({
        id: String(item.id),
        name: item.name,
        driverName: item.driverName,
        date: item.date,
        nombreHeures: item.totalHours != null ? String(item.totalHours) : '—',
      }));

      set({ oldSubmittedRoadMaps: mappedContent, loading: false, totalElements });
    } catch (error: any) {
      set({ error: error.message || 'Failed to fetch old submitted roadmaps', loading: false });
    }
  },
  createValidatedRoadMapsManually: async (payload: { driverIds: number[]; date: string }) => {
    set({ loading: true, error: null });
    try {
      const response = await axiosInstance.post(
        roadMapEndpoints.roadMap.validaRoadMap.add,
        payload
      );
      set({ loading: false });
      return response.data as ManualRoadMapCreationResult;
    } catch (error: any) {
      set({
        error: error.response?.data?.message || 'Erreur lors de la création des feuilles de route',
        loading: false,
      });
      throw new Error(
        error.response?.data?.message || 'Erreur lors de la création des feuilles de route'
      );
    }
  },

  getOldSubmittedRoadMapDetails: async (id) => {
    set({ loading: true, error: null });
    try {
      const response = await axiosInstance.get(
        roadMapEndpoints.roadMap.submittedRoadMap.getOldSubmittedRoadmapDetails(id)
      );
      set({ oldSubmittedRoadMapDetails: response.data, loading: false });
    } catch (error: any) {
      set({
        error: error.message || 'Failed to fetch old submitted roadmap details',
        loading: false,
      });
    }
  },
    getOldValidattedRoadMapDetails: async (id) => {
    set({ loading: true, error: null });
    try {
      const response = await axiosInstance.get(
        roadMapEndpoints.roadMap.validaRoadMap.getOldValidatedRoadmapDetails(id)
      );
      set({ oldValidattedRoadMapDetails: response.data, loading: false });
    } catch (error: any) {
      set({
        error: error.message || 'Failed to fetch old submitted roadmap details',
        loading: false,
      });
    }
  },

  getOldRoadMapByDriver: async (params) => {
    if (!params?.driverId) {
      set({ error: 'ID du chauffeur requis', loading: false });
      return;
    }

    set({ loading: true, error: null });
    try {
      const response = await axiosInstance.get(
        roadMapEndpoints.roadMap.validaRoadMap.getOldRoadmapByDriver(params.driverId),
        { params }
      );
      const { content, totalElements } = response.data;
      set({ validatedRoadMap: content, totalElements : totalElements, loading: false });
    } catch (error: any) {
      set({ error: error.message || 'Failed to fetch validatedRoadMap', loading: false });
    }
  },
  getAllDealValidRoadMap: async (params) => {
    set({ loading: true, error: null });
    try {
      const response = await axiosInstance.get(
        roadMapEndpoints.roadMap.validaRoadMap.getAllDelaValidRoadmap,
        { params }
      );
      const { content, totalElements } = response.data;
      set({ dealvalidatedRoadMap: content, totalElements: totalElements, loading: false });
    } catch (error: any) {
      set({ error: error.message || 'Failed to fetch validatedRoadMap', loading: false });
    }
  },
  getRoadMapStatistics: async () => {
    set({ loading: true, error: null });
    try {
      const response = await axiosInstance.get(roadMapEndpoints.roadMap.statistics.getStatistics);
      set({ roadMapStatistics: response.data, loading: false });
    } catch (error: any) {
      set({
        error: error.message || 'Erreur lors de la récupération des statistiques',
        loading: false,
      });
    }
  },

  createRoadMapsManually: async (payload: { driverIds: number[]; date: string }) => {
    set({ loading: true, error: null });
    try {
      const response = await axiosInstance.post(
        roadMapEndpoints.roadMap.submittedRoadMap.create,
        payload
      );

      set({ loading: false });
      return response.data as ManualRoadMapCreationResult;
    } catch (error: any) {
      set({
        error: error.response?.data?.message || 'Erreur lors de la création des feuilles de route',
        loading: false,
      });
      throw new Error(
        error.response?.data?.message || 'Erreur lors de la création des feuilles de route'
      );
    }
  },
  updateRoadMapStatus: async (id: number, newStatus: string) => {
    set({ loading: true, error: null });
    try {
      await axiosInstance.put(roadMapEndpoints.roadMap.validaRoadMap.updateStatus(id), {
        status: newStatus as RoadMapStatus,
      });
      set({ loading: false });
    } catch (error: any) {
      set({
        error: error.response?.data?.message || 'Erreur lors de la mise à jour du statut',
        loading: false,
      });
    }
  },
  getValidedRoadmap: async (id) => {
    set({ loading: true, error: null });
    try {
      const response = await axiosInstance.get(
        roadMapEndpoints.roadMap.validaRoadMap.getValidRoadmap.replace('{id}', id.toString())
      );
      const validatedRoadMapDetails = response.data;
      set({ validatedRoadMapDetails, loading: false });
    } catch (error: any) {
      set({ error: error.message || 'Failed to fetch validated Roadmap', loading: false });
    }
  },

  updateValidRoadmapStatus: async (id) => {
    set({ loading: true, error: null });
    try {
      await axiosInstance.post(
        roadMapEndpoints.roadMap.validaRoadMap.updateValidRoadmapStatus.replace(
          '{id}',
          id.toString()
        )
      );
      set({ loading: false });
    } catch (error: any) {
      set({
        error: error.message || 'Failed to update roadmap status',
        loading: false,
      });
    }
  },

  getGeolocData: async (driverId, year, month) => {
    set({ loading: true, error: null });
    try {
      const response = await axiosInstance.get(
        roadMapEndpoints.roadMap.validaRoadMap.getGeolocData
          .replace('{driverId}', driverId.toString())
          .replace('{year}', year.toString())
          .replace('{month}', month.toString())
      );
      const geolocData = response.data;
      set({ geolocData, loading: false });
    } catch (error: any) {
      set({ error: error.message || 'Failed to fetch Geoloc Data', loading: false });
    }
  },

  getPlanningData: async (driverId, date) => {
    set({ loading: true, error: null });
    try {
      const response = await axiosInstance.get(
        roadMapEndpoints.roadMap.validaRoadMap.getPlanningData
          .replace('{driverId}', driverId.toString())
          .replace('{date}', date.toString())
      );
      const planningData = response.data;
      set({ planningData, loading: false });
    } catch (error: any) {
      set({ error: error.message || 'Failed to fetch Driver Planning', loading: false });
    }
  },

  getDriverRoadMap: async (driverId, date) => {
    set({ loading: true, error: null });
    try {
      const response = await axiosInstance.get(
        roadMapEndpoints.roadMap.validaRoadMap.getDriverRoadMap
          .replace('{driverId}', driverId.toString())
          .replace('{date}', date.toString())
      );
      const driverRoadMapDetails = response.data;
      set({ driverRoadMapDetails, loading: false });
    } catch (error: any) {
      set({ error: error.message || 'Failed to fetch DriverRoadMap', loading: false });
    }
  },

  getCombinedTable: async (driverId, date) => {
    set({ loading: true, error: null });
    try {
      const response = await axiosInstance.get(
        roadMapEndpoints.roadMap.validaRoadMap.getCombinedTable
          .replace('{driverId}', driverId.toString())
          .replace('{date}', date.toString())
      );
      const combinedTable = response.data;
      set({ combinedTable, loading: false });
    } catch (error: any) {
      set({ error: error.message || 'Failed to fetch combinedTable', loading: false });
    }
  },

  createOrUpdateDailyRoadMap: async (validatedRoadMapId, combinedTableDayId, date, payload) => {
    set({ loading: true, error: null });
    try {
      await axiosInstance.post(
        roadMapEndpoints.roadMap.validaRoadMap.createUpdateDailyRoadMap
          .replace('{validatedRoadMapId}', validatedRoadMapId.toString())
          .replace('{combinedTableDayId}', combinedTableDayId.toString())
          .replace('{date}', date.toString()),
        payload
      );
      set({ loading: false });
    } catch (error: any) {
      set({ error: error.message || 'Failed to create/update roadmap', loading: false });
    }
  },
   updateSubmittedRoadMapStatus: async (id: number, isSubmitted: boolean) => {
    set({ loading: true, error: null });
    try {
      await axiosInstance.put(roadMapEndpoints.roadMap.submittedRoadMap.updateStatus(id), {
        isSubmitted: isSubmitted,
      });
      set({ loading: false });
    } catch (error: any) {
      set({
        error: error.response?.data?.message || 'Erreur lors de la mise à jour du statut',
        loading: false,
      });
    }
  },

  schedulePlanning: async (planningRequest: SchedulePlanningPayload) => {
    set({ loading: true, error: null });
    try {
      const response = await axiosInstance.post(
        roadMapEndpoints.planning.schedulePlanning, 
        planningRequest
      );
      set({ loading: false });
    } catch (error: any) {
      set({ error: error.message || 'Failed to schedule planning', loading: false });
    }
  },

   getAllPlanningRequest: async (params) => {
    set({ loading: true, error: null });
    try {
      const response = await axiosInstance.get(
        roadMapEndpoints.planning.getPlanningRequests,
        { params }
      );
      const { content, totalElements } = response.data;
      set({ planningRequests: content, totalElements: totalElements, loading: false });
    } catch (error: any) {
      set({ error: error.message || 'Failed to fetch validatedRoadMap', loading: false });
    }
  },
    getPlanningRequestDetails: async (id: number) => {
    set({ loading: true, error: null });
    try {
    const response =  await axiosInstance.get(roadMapEndpoints.planning.getPlanningRequestDetails(id));
      set({ planningRequestDetails: response.data, loading: false });
    } catch (error: any) {
      set({
        error: error.response?.data?.message || 'Erreur lors de la mise à jour du statut',
        loading: false,
      });
    }
  },
   getWorkedDaysDates: async (roadMapId: number) => {
    set({ loading: true, error: null });
    try {
    const response =  await axiosInstance.get(roadMapEndpoints.roadMap.submittedRoadMap.getWorkedDaysDates,
      { params: { roadMapId } }
     );
      set({ workedDaysDates: response.data, loading: false });
    } catch (error: any) {
      set({
        error: error.response?.data?.message || 'Erreur lors de récupération des jours travaillés',
        loading: false,
      });
    }
  },
}));
