import { create } from 'zustand';
import axiosInstance from '@/utils/axios';
import { appointmentEndpoints } from '@/shared/api/endpoints/hr/annual-appointments';
import { 
  IAppointmentType,
  AppointmentSearchParams,
  AppointmentPageResponse,
  IAppointment,
  BackendAppointmentStatus,
  BackendAppointmentType,
  CalendarEventDTO,
} from '@/shared/types/appointment';

const convertFrontendToBackend = (appointment: IAppointment): IAppointmentType => {
  const getBackendType = (frontType: string): BackendAppointmentType => {
    switch (frontType) {
      case 'Visite Médicale (médecine du travail)': return BackendAppointmentType.MEDICAL_VISIT;
      case 'Visite Médicale (Préfectorale)': return BackendAppointmentType.MEDICAL_PREFECTURE;
      case 'Entretien Annuel': return BackendAppointmentType.ANNUAL_INTERVIEW;
      case 'Formation': return BackendAppointmentType.TRAINING;
      case 'Autre': return BackendAppointmentType.OTHER;
      default: return BackendAppointmentType.OTHER;
    }
  };

  const getBackendStatus = (frontStatus: string): BackendAppointmentStatus => {
    switch (frontStatus) {
      case 'prevu': return BackendAppointmentStatus.SCHEDULED;
      case 'termine': return BackendAppointmentStatus.COMPLETED;
      case 'annule': return BackendAppointmentStatus.CANCELED;
      default: return BackendAppointmentStatus.SCHEDULED;
    }
  };

  return {
    appointmentType: getBackendType(appointment.type),
    appointmentStatus: getBackendStatus(appointment.status),
    medicalCenter: appointment.medicalCenterName || null,
    doctorName: appointment.doctorName || null,
    appointmentDate: appointment.date,
    timeSlot: appointment.time || null,
    additionalDetails: appointment.type === 'Autre' ? appointment.otherType : appointment.comments || null,
    driverId: appointment.driverId ? parseInt(appointment.driverId) : null,
    driverFirstName: null,
    driverLastName: null,
    driverFullName: appointment.driverName || null,
    driverEmail: null,
    driverPhone: null,
    isActive: true,
    createdDate: new Date().toISOString(),
    lastModifiedDate: new Date().toISOString(),
  };
};

type AppointmentStore = {
  appointments: IAppointmentType[];
  originalAppointments: IAppointmentType[];
  currentAppointment: IAppointmentType | null;
  calendarAppointments: CalendarEventDTO[];
  totalElements: number;
  totalPages: number;
  page: number;
  rowsPerPage: number;
  sortBy: string;
  sortDirection: string;
  loading: boolean;
  calendarLoading: boolean;
  error: string | null;
  successMessage: string | null;
  fetchAppointments: (params?: AppointmentSearchParams) => Promise<void>;
  fetchAppointmentDetails: (id: string | number) => Promise<IAppointmentType | null>;
  setPage: (page: number) => void;
  setRowsPerPage: (rowsPerPage: number) => void;
  setSorting: (sortBy: string, sortDirection: 'asc' | 'desc') => void;
  resetError: () => void;
  
  // CRUD operations
  createAppointment: (appointment: IAppointment) => Promise<boolean>;
  updateAppointment: (id: number, appointment: IAppointment) => Promise<boolean>;
  deleteAppointment: (id: number) => Promise<boolean>;
  cancelAppointment: (id: number) => Promise<boolean>;
  exportAppointments: (params: AppointmentSearchParams & { userId: number }) => Promise<string | null>;
  
  // Calendar operations
  fetchAppointmentsByDay: (date: string) => Promise<void>;
  fetchAppointmentsByWeek: (startDate: string) => Promise<void>;
  fetchAppointmentsByMonth: (year: number, month: number) => Promise<void>;
  clearCalendarAppointments: () => void;
};

export const useAppointmentStore = create<AppointmentStore>((set, get) => ({
  appointments: [],
  originalAppointments: [],
  currentAppointment: null,
  calendarAppointments: [],
  totalElements: 0,
  totalPages: 0,
  page: 0,
  rowsPerPage: 10,
  sortBy: 'id',
  sortDirection: 'desc',
  loading: false,
  calendarLoading: false,
  error: null,
  successMessage: null,

  resetError: () => set({ error: null, successMessage: null }),

  fetchAppointments: async (params) => {
    set({ loading: true, error: null });
    try {
      const { page, rowsPerPage, sortBy, sortDirection } = get();

      const queryParams = {
        ...params,
        page: params?.page ?? page,
        size: params?.size ?? rowsPerPage,
        sortBy: params?.sortBy ?? sortBy,
        sortDirection: params?.sortDirection ?? sortDirection,
      };

      const response = await axiosInstance.get<AppointmentPageResponse>(
        appointmentEndpoints.search,
        { params: queryParams }
      );

      const { content, totalElements, totalPages } = response.data;

      set({
        appointments: content,
        originalAppointments: content,
        totalElements,
        totalPages,
        loading: false,
        page: queryParams.page,
        rowsPerPage: queryParams.size,
        sortBy: queryParams.sortBy,
        sortDirection: queryParams.sortDirection,
      });
    } catch (error: any) {
      const message =
        error?.response?.data?.message ||
        error?.message ||
        'Échec de la récupération des rendez-vous';
      set({ error: message, loading: false });
    }
  },

  setPage: (page) => {
    set({ page });
    get().fetchAppointments({ page });
  },

  setRowsPerPage: (rowsPerPage) => {
    set({ rowsPerPage, page: 0 });
    get().fetchAppointments({ size: rowsPerPage, page: 0 });
  },

  setSorting: (sortBy: string, sortDirection: 'asc' | 'desc') => {
    set({ sortBy, sortDirection });
    get().fetchAppointments({ sortBy, sortDirection });
  },

  createAppointment: async (appointment: IAppointment) => {
    set({ loading: true, error: null, successMessage: null });
    try {
      const backendData = convertFrontendToBackend(appointment);
      
      const response = await axiosInstance.post(appointmentEndpoints.create, backendData);
      
      await get().fetchAppointments();
      
      set({ 
        loading: false, 
        successMessage: 'Rendez-vous créé avec succès',
        currentAppointment: response.data
      });
      
      return true;
    } catch (error: any) {
      const message =
        error?.response?.data?.message ||
        error?.message ||
        'Échec de la création du rendez-vous';
      
      set({ error: message, loading: false });
      return false;
    }
  },

  updateAppointment: async (id, appointment) => {
    set({ loading: true, error: null, successMessage: null });
    try {
      const backendData = convertFrontendToBackend(appointment);

      const response = await axiosInstance.put(
        appointmentEndpoints.update(id), 
        backendData
      );

      await get().fetchAppointments();

      set({
        loading: false,
        successMessage: 'Rendez-vous mis à jour avec succès',
        currentAppointment: response.data
      });

      return true;
    } catch (error: any) {
      const message =
        error?.response?.data?.message ||
        error?.message ||
        'Échec de la mise à jour du rendez-vous';

      set({
        error: message,
        loading: false,
        successMessage: null
      });

      return false;
    }
  },

  deleteAppointment: async (id) => {
    set({ loading: true, error: null, successMessage: null });
    try {
      await axiosInstance.delete(appointmentEndpoints.delete(id));
      await get().fetchAppointments();
      set({ loading: false, successMessage: 'Rendez-vous supprimé avec succès' });
      return true;
    } catch (error: any) {
      const message =
        error?.response?.data?.message ||
        error?.message ||
        'Échec de la suppression du rendez-vous';
      set({ error: message, loading: false });
      return false;
    }
  },

  cancelAppointment: async (id) => {
    set({ loading: true, error: null, successMessage: null });
    try {
      const response = await axiosInstance.put<IAppointmentType>(
        appointmentEndpoints.cancel(id)
      );

      await get().fetchAppointments();
      
      const { calendarAppointments } = get();
      if (calendarAppointments.length > 0) {
      }

      set({
        loading: false,
        successMessage: 'Rendez-vous annulé avec succès',
        currentAppointment: response.data
      });

      return true;
    } catch (error: any) {
      let message = 'Échec de l\'annulation du rendez-vous';
      
      if (error?.response?.data?.message) {
        message = error.response.data.message;
      } else if (error?.response?.status === 400) {
        message = 'Impossible d\'annuler ce rendez-vous. Il se peut qu\'il soit déjà annulé ou terminé.';
      } else if (error?.response?.status === 404) {
        message = 'Rendez-vous introuvable.';
      }

      set({
        error: message,
        loading: false,
        successMessage: null
      });

      return false;
    }
  },

  fetchAppointmentDetails: async (id) => {
    set({ loading: true, error: null });
    try {
      const response = await axiosInstance.get<IAppointmentType>(
        appointmentEndpoints.details(id)
      );
      const appointmentDetails = response.data;
      set({
        currentAppointment: appointmentDetails,
        loading: false
      });
      return appointmentDetails;
    } catch (error: any) {
      const message =
        error?.response?.data?.message ||
        error?.message ||
        'Échec de la récupération des détails du rendez-vous';
      set({ error: message, loading: false, currentAppointment: null });
      return null;
    }
  },

  exportAppointments: async (params) => {
    set({ loading: true, error: null });
    try {
      const response = await axiosInstance.post<{ ExportPath: string }>(
        appointmentEndpoints.export,
        null,
        { params }
      );

      return response.data.ExportPath;
    } catch (error: any) {
      const message =
        error?.response?.data?.message ||
        error?.message ||
        'Échec de l\'export des rendez-vous';
      set({ error: message, loading: false });
      return null;
    } finally {
      set({ loading: false });
    }
  },

  fetchAppointmentsByDay: async (date: string) => {
    set({ calendarLoading: true, error: null });
    try {
      const response = await axiosInstance.get<CalendarEventDTO[]>(
        appointmentEndpoints.calendarDay(date)
      );
      
      set({
        calendarAppointments: response.data,
        calendarLoading: false
      });
    } catch (error: any) {
      const message = error?.response?.data?.message || 'Échec de la récupération des rendez-vous du jour';
      set({ error: message, calendarLoading: false });
    }
  },

  fetchAppointmentsByWeek: async (startDate: string) => {
    set({ calendarLoading: true, error: null });
    try {
      const response = await axiosInstance.get<CalendarEventDTO[]>(
        appointmentEndpoints.calendarWeek(startDate)
      );
      
      set({
        calendarAppointments: response.data,
        calendarLoading: false
      });
    } catch (error: any) {
      const message = error?.response?.data?.message || 'Échec de la récupération des rendez-vous de la semaine';
      set({ error: message, calendarLoading: false });
    }
  },

  fetchAppointmentsByMonth: async (year: number, month: number) => {
    set({ calendarLoading: true, error: null });
    try {
      const response = await axiosInstance.get<CalendarEventDTO[]>(
        appointmentEndpoints.calendarMonth(year, month)
      );
      
      set({
        calendarAppointments: response.data,
        calendarLoading: false
      });
    } catch (error: any) {
      const message = error?.response?.data?.message || 'Échec de la récupération des rendez-vous du mois';
      set({ error: message, calendarLoading: false });
    }
  },

  clearCalendarAppointments: () => {
    set({ calendarAppointments: [] });
  },
})); 