import {
  Dialog,
  DialogTitle,
  DialogContent,
  DialogActions,
  Button,
  Stack,
  TextField,
  MenuItem,
  Typography,
  Box,
  IconButton,
  Chip,
  FormControl,
  InputLabel,
  Select,
  Switch,
  FormControlLabel,
  SelectChangeEvent,
  Grid,
  InputAdornment
} from '@mui/material';
import { DateTimePicker, TimePicker } from '@mui/x-date-pickers';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { 
  faXmark, 
  faCloudUpload, 
  faBell,
  faTrash,
  faClock,
  faCalendar
} from '@fortawesome/free-solid-svg-icons';
import { useRef, useState, useEffect } from 'react';
import FormField from "@/shared/components/form/form-field";
import { ModeType } from "@/shared/types/common";
import { 
  NOTIFICATION_INTERVALS,
  EVENT_TYPES,
  EMPLOYEE_TYPES,
  DIALOG_CONSTANTS,
  EVENT_FORM_FIELDS,
  FILTER_COLUMNS,
  STATUS_OPTIONS
} from '../constants/event.constants';
import { format, parseISO, addDays, addWeeks, addMonths, isBefore } from 'date-fns';
import FontAwesome from '@/shared/components/fontawesome';
import { CalendarEvent, FormField as IFormField } from '../types/calendar-types';
import { MOCK_DRIVERS, MOCK_AGENCIES } from '@/shared/_mock/_employeeEvents';
import { StyledDialog, StyledDialogTitle } from '../../styles';
import { Formik, Form } from 'formik';
import { eventSchema } from '../utils/event-schema';
import { useCalendarStore } from '@/shared/api/stores/hr-service/calendarStore';
import { IDriver } from '@/shared/types/driver';
import { IAgency } from '@/shared/types/infrastructure';
import { useSnackbar } from 'notistack';
import { CollaboratorDTO } from '@/shared/types/collaborator';

const INITIAL_EVENT_DATA = {
  employeeType: 'DRIVER' as const,
  type: '',
  employeeId: '',
  agenceId: '',
  date: new Date(),
  notes: '',
  notifications: [] as string[],
  isAllDay: true,
  files: [] as File[],
  hour: '',
  status: 'PENDING'
};

interface AddEventDialogProps {
  open: boolean;
  onClose: () => void;
  onSubmit: (eventData: any) => void;
  initialEvent?: any;
  isEditing?: boolean;
}

interface EventData {
  employeeType: 'DRIVER' | 'SEDENTARY';
  type: string;
  employeeId: string;
  agenceId: string;
  date: Date;
  notes: string;
  notifications: string[];
  isAllDay: boolean;
  files?: File[];
  hour: string;
  status:String;
}

const parseNotificationInterval = (interval: string) => {
  const unit = interval.slice(-1);
  const value = parseInt(interval.slice(0, -1));
  
  switch (unit) {
    case 'j':
      return { value, unit: 'days' };
    case 's':
      return { value, unit: 'weeks' };
    case 'm':
      return { value, unit: 'months' };
    default:
      return { value: 0, unit: 'days' };
  }
};

const calculateNotificationTime = (eventDate: Date, eventHour: string, interval: string) => {
  const [hours, minutes] = eventHour.split(':').map(Number);
  const eventDateTime = new Date(eventDate);
  eventDateTime.setHours(hours, minutes, 0, 0);
  
  const { value, unit } = parseNotificationInterval(interval);
  
  let notificationTime = new Date(eventDateTime);
  
  switch (unit) {
    case 'days':
      notificationTime = addDays(notificationTime, -value);
      break;
    case 'weeks':
      notificationTime = addWeeks(notificationTime, -value);
      break;
    case 'months':
      notificationTime = addMonths(notificationTime, -value);
      break;
  }
  
  return notificationTime;
};

const validateNotifications = (eventDate: Date, eventHour: string, notifications: string[]) => {
  const now = new Date();
  const invalidNotifications = [];
  
  for (const notification of notifications) {
    const notificationTime = calculateNotificationTime(eventDate, eventHour, notification);
    
    if (isBefore(notificationTime, now)) {
      const notificationLabel = NOTIFICATION_INTERVALS.find(n => n.value === notification)?.label || notification;
      
      invalidNotifications.push({
        interval: notification,
        label: notificationLabel,
        calculatedTime: notificationTime
      });
    }
  }
  
  return invalidNotifications;
};



export default function AddEventDialog({ 
  open, 
  onClose, 
  onSubmit, 
  initialEvent,
  isEditing = false 
}: AddEventDialogProps) {
  const { enqueueSnackbar } = useSnackbar();
  const { 
    createEvent, 
    updateEvent, 
    loading, 
    error,
    drivers,
    agencies,
    notificationIntervals,
    collaborators,
    fetchDrivers,
    fetchAgencies,
    fetchNotificationIntervals,
    fetchCollaboratorsByAgency
  } = useCalendarStore();

  const [selectedAgency, setSelectedAgency] = useState<string | undefined>(initialEvent?.agenceId);

  useEffect(() => {
    if (open) {
      fetchDrivers();
      fetchAgencies();
      fetchNotificationIntervals();
    }
  }, [open, fetchDrivers, fetchAgencies, fetchNotificationIntervals]);

  useEffect(() => {
    if (open && initialEvent?.employeeType === 'SEDENTARY' && initialEvent?.agenceId) {
      fetchCollaboratorsByAgency(initialEvent.agenceId);
    }
  }, [open, initialEvent?.employeeType, initialEvent?.agenceId, fetchCollaboratorsByAgency]);
  useEffect(() => {
    if (open && selectedAgency) {
      fetchCollaboratorsByAgency(selectedAgency);
    }
  }, [open, selectedAgency, fetchCollaboratorsByAgency]);

  const initialValues = {
    ...INITIAL_EVENT_DATA,
    employeeType: 'DRIVER',
    ...initialEvent && {
      type: initialEvent.type,
      employeeType: initialEvent.employeeType || 'DRIVER',
      employeeId: initialEvent.employeeId,
      agenceId: initialEvent.agenceId ? String(initialEvent.agenceId) : '',
      date: initialEvent.start ? new Date(initialEvent.start) : new Date(),
      notes: initialEvent.notes,
      notifications: initialEvent.notifications || [],
      isAllDay: initialEvent.allDay ?? true,
      hour: initialEvent.hour,
      status: initialEvent.status || 'PENDING',
    }
  };

  const handleSubmit = async (values: EventData) => {
    try {
      if (values.notifications && values.notifications.length > 0 && values.hour) {
        const invalidNotifications = validateNotifications(
          values.date, 
          values.hour, 
          values.notifications
        );
        
        if (invalidNotifications.length > 0) {
          enqueueSnackbar(
            "Attention: Certaines notifications ne peuvent pas être programmées car l'heure de notification est antérieure à l'heure actuelle. L'événement sera créé sans ces notifications.",
            { 
              variant: 'warning',
              autoHideDuration: 8000
            }
          );
          
          const validNotifications = values.notifications.filter(notification => {
            const notificationTime = calculateNotificationTime(values.date, values.hour, notification);
            return !isBefore(notificationTime, new Date());
          });
          
          values.notifications = validNotifications;
        }
      }

      const eventDate = values.date instanceof Date ? values.date : new Date(values.date);
      const dateOnly = format(eventDate, 'yyyy-MM-dd');

      const eventData = {
        ...values,
        date: dateOnly, 
        employeeId: values.employeeId,
        status: values.status || "PENDING",
        ...(values.employeeType === 'SEDENTARY' && values.agenceId && { agencyId: values.agenceId }),
      };

      if (isEditing && initialEvent?.id) {
        await updateEvent(initialEvent.id, eventData);
        enqueueSnackbar('Événement mis à jour avec succès', { variant: 'success' });
      } else {
        await createEvent(eventData);
        enqueueSnackbar('Événement créé avec succès', { variant: 'success' });
      }
      
      onSubmit(values);
      onClose();
    } catch (error: any) {
      enqueueSnackbar(
        error.response?.data?.message || 'Une erreur est survenue', 
        { variant: 'error' }
      );
    }
  };
  const driverOptions = loading
    ? [{ value: '', label: 'Chargement des chauffeurs...' }]
    : (drivers.length > 0 
        ? drivers.map(driver => ({
            value: String(driver.id), 
            label: `${driver.firstName} ${driver.lastName}`.trim()
          }))
        : [{ value: '', label: 'Aucun chauffeur trouvé' }]);

  const agencyOptions = agencies.length > 0 
    ? agencies.map(agency => ({
        value: String(agency.id),
        label: agency.name
      }))
    : Array.from(MOCK_AGENCIES);

  const notificationOptions = notificationIntervals.length > 0 
    ? notificationIntervals 
    : Array.from(NOTIFICATION_INTERVALS);

  return (
    <StyledDialog 
      open={open} 
      onClose={onClose}
      maxWidth="md"
      fullWidth
      PaperProps={{
        sx: {
          borderRadius: 2,
          backgroundImage: 'linear-gradient(135deg, rgba(255,255,255,0.95) 0%, rgba(240,242,245,0.95) 100%)',
          backdropFilter: 'blur(20px)',
        }
      }}
    >
      <StyledDialogTitle sx={{ pb: 3, display: 'flex', justifyContent: 'space-between', alignItems: 'center',color: 'primary.main' }}>
        <Typography variant="h6">
          {isEditing ? DIALOG_CONSTANTS.TITLES.EDIT : DIALOG_CONSTANTS.TITLES.CREATE}
        </Typography>
        <IconButton 
          onClick={onClose} 
          size="small"
          sx={{ 
            position: 'absolute',
            right: 8,
            top: 8
          }}
        >
          <FontAwesomeIcon icon={faXmark} />
        </IconButton>
      </StyledDialogTitle>

      <Formik
        initialValues={initialValues}
        validationSchema={eventSchema}
        onSubmit={handleSubmit}
        enableReinitialize
      >
        {({ values, setFieldValue, errors, touched }) => (
          <Form>
            <DialogContent sx={{ p: 3 }}>
              <Grid container spacing={4}>
                <Grid item xs={12} sm={6}>
                  <FormField
                    field={{
                      name: 'employeeType',
                      label: 'Type d\'employé',
                      type: 'select',
                      options: Array.from(EMPLOYEE_TYPES)
                    }}
                    value={values.employeeType}
                    onChange={(name, value) => {
                      setFieldValue(name, value);
                      setFieldValue('employeeId', '');
                      setFieldValue('agenceId', '');
                      setSelectedAgency(undefined);
                    }}
                    error={touched.employeeType ? (errors.employeeType as string | undefined) : undefined}
                    isReadOnly={false}
                  />
                </Grid>
                {values.employeeType === 'DRIVER' && (
                  <Grid item xs={12} sm={6}>
                    <FormField
                      field={{
                        name: 'employeeId',
                        label: 'Chauffeur',
                        type: 'select',
                        options: driverOptions
                      }}
                      value={values.employeeId}
                      onChange={(name, value) => setFieldValue(name, value)}
                      error={touched.employeeId ? (errors.employeeId as string | undefined) : undefined}
                      isReadOnly={false}
                    />
                  </Grid>
                )}
                {values.employeeType === 'SEDENTARY' && (
                  <Grid item xs={12} sm={6}>
                    <FormField
                      field={{
                        name: 'agenceId',
                        label: 'Agence',
                        type: 'select',
                        options: agencyOptions
                      }}
                      value={values.agenceId}
                      onChange={(name, value) => {
                        setFieldValue(name, String(value));
                        setFieldValue('employeeId', ''); 
                        setSelectedAgency(value); 
                      }}
                      error={touched.agenceId ? (errors.agenceId as string | undefined) : undefined}
                      isReadOnly={false}
                    />
                  </Grid>
                )}
                {values.employeeType === 'SEDENTARY' && values.agenceId && (
                  <Grid item xs={12} sm={6}>
                    <FormField
                      field={{
                        name: 'employeeId',
                        label: 'Agent',
                        type: 'select',
                        options: collaborators.map(agent => ({
                          value: agent.id.toString(),
                          label: `${agent.firstName} ${agent.lastName}`
                        }))
                      }}
                      value={values.employeeId}
                      onChange={(name, value) => setFieldValue(name, value)}
                      error={touched.employeeId ? (errors.employeeId as string | undefined) : undefined}
                      isReadOnly={false}
                    />
                  </Grid>
                )}

                  <Grid item xs={12} sm={6}>
                    <FormField
                      field={{
                        name: 'type',
                        label: 'Type d\'événement',
                        type: 'select',
                        options: Array.from(EVENT_TYPES)
                      }}
                      value={values.type}
                      onChange={(name, value) => setFieldValue(name, value)}
                      error={touched.type ? (errors.type as string | undefined) : undefined}
                      isReadOnly={false}
                    />
                  </Grid>

                  <Grid item xs={12} sm={6}>
                    <FormField
                      field={{
                        name: 'status',
                        label: 'Statut',
                        type: 'select',
                        options: STATUS_OPTIONS.map(status => ({
                          value: status.value,
                          label: status.label
                        }))
                      }}
                      value={values.status}
                      onChange={(name, value) => setFieldValue(name, value)}
                      error={touched.status ? (errors.status as string | undefined) : undefined}
                      isReadOnly={false}
                    />
                  </Grid>

                  <Grid item xs={12} sm={6}>
                    <FormField
                      field={{
                        name: 'date',
                        label: 'Date',
                        type: 'date',
                        icon: faCalendar
                      }}
                      value={values.date}
                      onChange={(name, value) => setFieldValue(name, value)}
                      error={touched.date ? (errors.date as string | undefined) : undefined}
                      isReadOnly={false}
                    />
                  </Grid>
                  <Grid item xs={12} sm={6}>
                    <FormField
                      field={{
                        name: 'hour',
                        label: 'Heure',
                        type: 'time',
                        icon: faClock
                      }}
                      value={values.hour}
                      onChange={(name, value) => setFieldValue(name, value)}
                      error={touched.hour ? (errors.hour as string | undefined) : undefined}
                      isReadOnly={false}
                    />
                  </Grid>
                  <Grid item xs={12} sm={6}>
                    <FormField
                      field={{
                        name: 'notes',
                        label: 'Commentaires et notes',
                        type: 'textarea',
                        placeholder: 'Ajouter un commentaire...'
                      }}
                      value={values.notes}
                      onChange={(name, value) => setFieldValue(name, value)}
                      error={touched.notes ? (errors.notes as string | undefined) : undefined}
                      isReadOnly={false}
                    />
                  </Grid>

                  <Grid item xs={12}>
                    <FormField
                      field={{
                        name: 'notifications',
                        label: 'Notifications',
                        type: 'multiple',
                        placeholder: "Sélectionnez une ou plusieurs notifications",
                        options: notificationOptions
                      }}
                      value={values.notifications}
                      onChange={(name, value) => {
                        setFieldValue(name, value);
                      }}
                      error={touched.notifications ? (errors.notifications as string | undefined) : undefined}
                      isReadOnly={false}
                    />
                  </Grid>

                  <Grid item xs={12}>
                    <Box sx={{ border: '1px dashed', borderColor: 'divider', borderRadius: 1, p: 3 }}>
                      <Stack spacing={2} alignItems="center">
                        <input
                          type="file"
                          id="file-upload"
                          multiple
                          style={{ display: 'none' }}
                          onChange={(event) => {
                            if (event.target.files) {
                              const newFiles = Array.from(event.target.files);
                              setFieldValue('files', [...(values.files || []), ...newFiles]);
                            }
                          }}
                        />
                        <label htmlFor="file-upload">
                          <Button
                            component="span"
                            variant="outlined"
                            startIcon={<FontAwesomeIcon icon={faCloudUpload} />}
                          >
                            {DIALOG_CONSTANTS.BUTTONS.ADD_DOCUMENTS}
                          </Button>
                        </label>
                        <Box sx={{ width: '100%', textAlign: 'center' }}>
                          {(!values.files || values.files.length === 0) ? (
                            <Typography color="text.secondary" variant="body2">
                              Aucun document ajouté
                            </Typography>
                          ) : (
                            <Stack spacing={1} width="100%">
                              {values.files.map((file, index) => (
                                <Chip
                                  key={index}
                                  label={file.name}
                                  onDelete={() => {
                                    const newFiles = values.files?.filter((_, i) => i !== index);
                                    setFieldValue('files', newFiles);
                                  }}
                                  sx={{ justifyContent: 'space-between' }}
                                />
                              ))}
                            </Stack>
                          )}
                        </Box>
                      </Stack>
                    </Box>
                  </Grid>

                  <Grid item xs={12}>
                    <FormControlLabel
                      control={
                        <Switch
                          checked={values.isAllDay}
                          onChange={(e) => setFieldValue('isAllDay', e.target.checked)}
                        />
                      }
                      label="Toute la journée"
                    />
                  </Grid>
                </Grid>
              </DialogContent>

              <DialogActions sx={{ p: 3, pt: 0 }}>
                <Button onClick={onClose} variant="outlined" disabled={loading}>
                  {DIALOG_CONSTANTS.BUTTONS.CANCEL}
                </Button>
                <Button 
                  type="submit"
                  variant="contained"
                  disabled={loading || !values.type || !(values.employeeId || values.agenceId)}
                >
                  {loading ? 'Chargement...' : (isEditing ? DIALOG_CONSTANTS.BUTTONS.SAVE : DIALOG_CONSTANTS.BUTTONS.CREATE)}
                </Button>
              </DialogActions>
            </Form>
          )}
      </Formik>
    </StyledDialog>
  );
} 