'use client';

import { useState, useRef, useMemo, useEffect } from 'react';
import { Container, Box, Alert, Snackbar } from '@mui/material';
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { fr } from 'date-fns/locale';
import { format } from 'date-fns';
import dayGridPlugin from '@fullcalendar/daygrid';
import timeGridPlugin from '@fullcalendar/timegrid';
import interactionPlugin from '@fullcalendar/interaction';
import { ScheduleToolbar } from './schedule-toolbar';
import EventDetailsDialog from './event-details-dialog';
import AddEventDialog from './add-event-dialog';
import FullCalendar from '@fullcalendar/react';
import { StyledCalendarContainer } from '../styles/calendar-styles';
import { CALENDAR_VIEWS, TIME_SETTINGS, FILTER_COLUMNS, CALENDAR_CONFIG, STATUS_OPTIONS, EMPLOYEE_TYPES } from '../constants/event.constants';
import { CalendarViewType, FilterType, AgencyType, StatusType, CalendarEvent } from '../types/calendar-types';
import { type TableConfig, useTableManager } from "@/hooks/use-table-manager"
import { TableType } from "@/shared/types/common"
import { useCalendarStore } from '@/shared/api/stores/hr-service/calendarStore';
import { useSnackbar } from 'notistack';
import { CreateEventRequest } from '@/shared/api/stores/hr-service/calendarStore';
import { EventDropArg } from '@fullcalendar/core';
import { CalendarEventResponse } from '@/shared/api/stores/hr-service/calendarStore';
import { EventStatus } from '../types/calendar-types';

const mapBackendEventsToCalendar = (events: CalendarEventResponse[]): CalendarEvent[] => {
  return events.map(event => {
    const startDate = new Date(event.date);
    if (event.hour) {
      const [hours, minutes] = event.hour.split(':');
      startDate.setHours(parseInt(hours, 10));
      startDate.setMinutes(parseInt(minutes, 10));
    }


    return {
      id: event.id?.toString() || '',
      title: event.hour ? event.hour : format(startDate, 'HH:mm'),
      start: startDate.toISOString(),
      end: startDate.toISOString(),
      allDay: event.isAllDay,
      type: event.type,
      color: '#1976d2',
      agence: (event as any).agence || '',
      driverStatus: event.status,
      status: event.status as EventStatus,
      employeeId: event.employeeId || '',
      employeeType: event.employeeType,
      employeeName: event.employeeName,
      date: event.date,
      hour: event.hour,
      notes: event.notes,
      description: event.notes,
      notifications: event.notifications,
      files: event.files,
      comments: ""
    };
  });
};



const calendarConfig: TableConfig<CalendarEvent> = {
  type: "calendar",
  initialData: [],  
  defaultTableHead: [
    { id: "employeeType", label: "Type d'employé", 
      type: "status", 
      options: EMPLOYEE_TYPES.map(opt => ({
        value: opt.value,
        label: opt.label
      })) },
    { id: "agency", label: "Agence", type: "text" },
    { 
      id: "driverStatus", 
      label: "Statut", 
      type: "status", 
      options: STATUS_OPTIONS.map(opt => ({
        value: opt.value,
        label: opt.label
      }))
    },
     { id: "employeeName", label: "Employé", type: "text" },
    { id: "start", label: "Date de début", type: "date" },
    { id: "end", label: "Date de Fin", type: "date" },
    { id: "title", label: "Titre", type: "text" }
    
  ]
}

export default function RHCalendarView() {
  const { enqueueSnackbar } = useSnackbar();
  const { 
    loading, 
    error, 
    updateEvent  
  } = useCalendarStore();
  const [currentDate, setCurrentDate] = useState(new Date());
  const [view, setView] = useState<CalendarViewType>(CALENDAR_VIEWS.MONTH);
  const calendarRef = useRef<FullCalendar>(null);
  const [selectedEvent, setSelectedEvent] = useState<CalendarEvent | null>(null);
  const [openEventDialog, setOpenEventDialog] = useState(false);
  const [openAddDialog, setOpenAddDialog] = useState(false);
  const [showSuccess, setShowSuccess] = useState(false);
  const [isEventDialogOpen, setIsEventDialogOpen] = useState(false);
  const [zoom, setZoom] = useState<number>(CALENDAR_CONFIG.ZOOM_DEFAULT);
  const { events, fetchEvents } = useCalendarStore();
  const [calendarEvents, setCalendarEvents] = useState<CalendarEvent[]>([]);

  const mappedEvents = useMemo(() => mapBackendEventsToCalendar(events), [events]);

const {
  filteredData: filteredEvents,
  tableHead,
  handleFilterChange,
  handleResetFilters, 
} = useTableManager<CalendarEvent>({
  type: "calendar",
  initialData: mappedEvents,  
  defaultTableHead: calendarConfig.defaultTableHead,
});

  

useEffect(() => {
  if (events && events.length > 0) {
    const mapped = mapBackendEventsToCalendar(events);
    setCalendarEvents(mapped);
  }
}, [events]);
useEffect(() => {
  fetchEvents();
}, [fetchEvents]);


  useEffect(() => {
    if (error) {
      enqueueSnackbar(error, { variant: 'error' });
    }
  }, [error, enqueueSnackbar]);

  const handleEventClick = (info: any) => {
    const employeeEvent = {
      ...info.event.extendedProps,
      id: info.event.id,
      start: info.event.start?.toISOString() || new Date().toISOString(),
      end: info.event.end?.toISOString() || new Date().toISOString(),
      allDay: info.event.allDay,
      title: info.event.title
    };


    let eventStart = new Date(employeeEvent.start);
    if (employeeEvent.hour) {
      const [hours, minutes] = employeeEvent.hour.split(':');
      eventStart.setHours(parseInt(hours, 10));
      eventStart.setMinutes(parseInt(minutes, 10));
    }

    const calendarEvent: CalendarEvent = {
      id: employeeEvent.id || '',
      title: employeeEvent.title || '',
      start: eventStart.toISOString(),
      end: employeeEvent.end,
      allDay: employeeEvent.allDay,
      type: employeeEvent.type as FilterType,
      color: employeeEvent.color || '#B7B7B7',
      agence: employeeEvent.agence || '',
      employeeType: employeeEvent.employeeType || 'DRIVER',
      employeeId: employeeEvent.employeeId || '',
      employeeName: employeeEvent.employeeName || employeeEvent.title || '',
      date: employeeEvent.date,
      hour: employeeEvent.hour,
      notes: employeeEvent.notes || '',
      notifications: employeeEvent.notifications || [],
      files: employeeEvent.files?.map((doc: { name: string; type: string }) => new File([], doc.name, { type: doc.type })) || [],
      description: employeeEvent.notes || '',
      comments: Array.isArray(employeeEvent.comments) 
        ? employeeEvent.comments.map((c: { text: string }) => c.text).join('\n') 
        : '',
      status: employeeEvent.status || 'PENDING'
    };


    setSelectedEvent(calendarEvent);
    setOpenEventDialog(true);
  };

  const handleAddEvent = async (eventData: any) => {
    try {
      await fetchEvents(); 
      setOpenAddDialog(false);
      enqueueSnackbar('Événement créé avec succès', { variant: 'success' });
    } catch (error) {
      enqueueSnackbar('Erreur lors de la création de l\'événement', { variant: 'error' });
    }
  };

  const handleViewChange = (newView: CalendarViewType) => {
    setView(newView);
    if (calendarRef.current) {
      const calendarApi = calendarRef.current.getApi();
      calendarApi.changeView(newView);
    }
  };


  
  const handleDateChange = (newDate: Date) => {    
    if (calendarRef.current) {
      const calendarApi = calendarRef.current.getApi();
      calendarApi.gotoDate(newDate);
      setCurrentDate(newDate);
    }
  };

  const handlePrint = () => {
    window.print();
  };

  const handleCreateEvent = () => {
    setOpenAddDialog(true);
  };

  const handleCloseEventDialog = () => {
    setIsEventDialogOpen(false);
  };

  const handleZoomChange = (newZoom: number) => {
    setZoom(newZoom);
    window.dispatchEvent(new Event('resize'));
  };

  const handleEventUpdate = (updatedEvent: CalendarEvent) => {    
    setOpenEventDialog(false);
  };

  const handleUpdateEvent = async (updatedEvent: CalendarEvent) => {

    const eventId = parseInt(updatedEvent.id);
    if (isNaN(eventId)) {
      enqueueSnackbar('ID de l\'événement invalide', { variant: 'error' });
      return;
    }

    const { id, allDay, start, end, color, title, description, ...eventData } = updatedEvent;
    const updateData: CreateEventRequest = {
      ...eventData,
      isAllDay: allDay,
      date: start,
      notifications: updatedEvent.notifications || []
    };
    
    try {
      await updateEvent(eventId, updateData);
      await fetchEvents(); 
      enqueueSnackbar('Événement mis à jour avec succès', { variant: 'success' });
    } catch (error) {
      console.error('Update error:', error);
      enqueueSnackbar('Erreur lors de la mise à jour', { variant: 'error' });
    }
  };

  const handleEventDrop = async (dropInfo: EventDropArg) => {
    const eventId = parseInt(dropInfo.event.id);
    if (isNaN(eventId)) {
      enqueueSnackbar('ID de l\'événement invalide', { variant: 'error' });
      return;
    }

    try {
      const currentEvent = events.find(e => Number(e.id) === eventId);
      if (!currentEvent) {
        throw new Error('Événement non trouvé');
      }

      const updateData: CreateEventRequest = {
        employeeType: dropInfo.event.extendedProps.employeeType || 'DRIVER',
        type: dropInfo.event.extendedProps.type,
        employeeId: currentEvent.employeeId,
        date: dropInfo.event.start?.toISOString() || new Date().toISOString(),
        hour: format(dropInfo.event.start || new Date(), 'HH:mm'),
        notes: dropInfo.event.extendedProps.notes || '',
        notifications: dropInfo.event.extendedProps.notifications || [],
        isAllDay: dropInfo.event.allDay,
        status: dropInfo.event.extendedProps.status || 'PENDING'
      };

      await updateEvent(eventId, updateData);
      await fetchEvents();
      enqueueSnackbar('Événement déplacé avec succès', { variant: 'success' });
    } catch (error: any) {
      console.error('Drop error:', error);
      dropInfo.revert();
      enqueueSnackbar(error.response?.data?.message || 'Erreur lors du déplacement', { variant: 'error' });
    }
  };




  
  

  return (
    <LocalizationProvider dateAdapter={AdapterDateFns} adapterLocale={fr}>
      <Container maxWidth={false} sx={{ '& .fc-day': { backgroundColor: '#fff' }, p: 3 }}>
        <Box sx={{ mb: 1 }}>
          <ScheduleToolbar
            date={currentDate}
            view={view}
            onViewChange={handleViewChange}
            onDateChange={handleDateChange}
            onZoomChange={handleZoomChange}
            onFilters={handleFilterChange}
            onResetFilters={handleResetFilters}
            onCreateEvent={handleCreateEvent}
            initialColumns={tableHead}
            type={TableType.Calendar}
            viewMode="calendar"
            onViewToggle={() => {}}
          />
        </Box>

        {/* Calendar component */}
        <StyledCalendarContainer zoom={zoom}>
          <FullCalendar
            ref={calendarRef}
            plugins={[dayGridPlugin, timeGridPlugin, interactionPlugin]}
            weekends
            editable
            selectable
            displayEventTime={false}
            eventDrop={handleEventDrop}
            events={filteredEvents}
            firstDay={1}
            locale="fr"
            initialView={view}
            headerToolbar={false}
            dayMaxEventRows={false}
            eventDisplay="block"
            height="100%"
            dayHeaderFormat={{ weekday: 'long' }}
            slotMinTime="08:00:00"
            slotMaxTime="19:00:00"
            slotDuration="01:00:00"
            views={{
              dayGridMonth: {
                dayMaxEventRows: false,
              },
              timeGridWeek: {
                dayMaxEventRows: false,
                dayHeaderFormat: { weekday: 'long' },
                slotDuration: '01:00:00',
                slotLabelFormat: {
                  hour: '2-digit',
                  minute: '2-digit',
                  hour12: false
                },
                allDaySlot: true,
                allDayText: 'Journée entière',
                headerToolbar: false,
                nowIndicator: true,
              },
              timeGridDay: {
                slotDuration: '01:00:00',
                displayEventEnd: true,
                nowIndicator: true,
                eventMaxStack: 2,
                slotEventOverlap: false,
                allDaySlot: true,
                allDayText: 'Journée entière',
                slotLabelFormat: {
                  hour: '2-digit',
                  minute: '2-digit',
                  hour12: false
                }
              },
            }}
            eventClick={handleEventClick}
            datesSet={(arg) => {
            }}
          />
        </StyledCalendarContainer>

        {/* Dialogs */}
        <EventDetailsDialog
          event={selectedEvent || {
            id: '',
            title: '',
            start: new Date().toISOString(),
            end: new Date().toISOString(),
            allDay: false,
            type: 'custom',
            color: '#B7B7B7',
            agence: 'all',
            employeeType: 'DRIVER',
            date: new Date().toISOString(),
            status: 'PENDING'
          }}
          open={openEventDialog}
          onClose={() => {
            setOpenEventDialog(false);
            setSelectedEvent(null);
          }}
          onEventUpdate={handleUpdateEvent}
        />

        <AddEventDialog
          open={openAddDialog}
          onClose={() => setOpenAddDialog(false)}
          onSubmit={handleAddEvent}
        />

        {/* Success Snackbar */}
        <Snackbar
          open={showSuccess}
          autoHideDuration={4000}
          onClose={() => setShowSuccess(false)}
          anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
        >
          <Alert 
            onClose={() => setShowSuccess(false)} 
            severity="success" 
            variant="filled"
            sx={{ width: '100%' }}
          >
            Événement créé avec succès
          </Alert>
        </Snackbar>
      </Container>
    </LocalizationProvider>
  );
} 