import React, { useState, useCallback, useMemo, useEffect } from 'react';
import {
  Box,
  Typography,
  Grid,
  Button,
  Chip,
  IconButton,
  Dialog,
  DialogTitle,
  DialogContent,
  DialogActions,
  FormControl,
  InputLabel,
  Select,
  MenuItem,
  Alert,
  Tooltip,
} from '@mui/material';
import { Add as AddIcon, Delete as DeleteIcon, Edit as EditIcon } from '@mui/icons-material';
import { useFormik } from 'formik';
import * as Yup from 'yup';
import type { WorkingHoursSlot } from '@/shared/types/working-hours';
import { DAY_NAMES, TIME_SLOTS, formatTime, getDayName } from '@/shared/types/working-hours';
import { useWorkingHours } from '../hooks/use-working-hours';
import { useSnackbar } from 'notistack';
import ConditionalComponent from '@/shared/components/table/ConditionalComponent';

interface WorkingHoursSelectorProps {
  workingHours: WorkingHoursSlot[];
  onChange: (workingHours: WorkingHoursSlot[]) => void;
  disabled?: boolean;
  employeeId?: string; // Add employeeId to make API calls
}

interface WorkingHoursFormData {
  dayOfWeek: number;
  startHour: number;
  endHour: number;
}

const validationSchema = Yup.object({
  dayOfWeek: Yup.number().min(1).max(7).required('Jour requis'),
  startHour: Yup.number().min(8).max(23).required('Heure de début requise'),
  endHour: Yup.number().min(8).max(23).required('Heure de fin requise'),
});

export default function WorkingHoursSelector({
  workingHours,
  onChange,
  disabled = false,
  employeeId
}: WorkingHoursSelectorProps) {
  const [isDialogOpen, setIsDialogOpen] = useState(false);
  const [editingSlot, setEditingSlot] = useState<WorkingHoursSlot | null>(null);

  // Working hours hook for API calls
  const {
    createWorkingHours,
    updateWorkingHoursSlot,
    deleteWorkingHoursSlot,
    loadWorkingHours,
    creating,
    updating,
    deleting
  } = useWorkingHours(employeeId);
  const { enqueueSnackbar } = useSnackbar();

  // Auto-load working hours when employeeId changes
  useEffect(() => {
    if (employeeId && employeeId !== 'new') {
      loadWorkingHours(employeeId).then((slots) => {
        onChange(slots);
      }).catch((error) => {
        console.error('Error loading working hours:', error);
      });
    }
  }, [employeeId]);

  const workingHoursByDay = useMemo(() => {
    const grouped: { [key: number]: WorkingHoursSlot[] } = {};
    workingHours.forEach(slot => {
      if (!grouped[slot.dayOfWeek]) {
        grouped[slot.dayOfWeek] = [];
      }
      grouped[slot.dayOfWeek].push(slot);
    });
    return grouped;
  }, [workingHours]);


  const hasOverlap = useCallback((newSlot: WorkingHoursSlot, excludeId?: string) => {
    return workingHours.some(slot => {
      if (excludeId && slot.id === excludeId) return false;
      if (slot.dayOfWeek !== newSlot.dayOfWeek) return false;


      return (newSlot.startHour < slot.endHour && newSlot.endHour > slot.startHour);
    });
  }, [workingHours]);

  const formik = useFormik<WorkingHoursFormData>({
    initialValues: {
      dayOfWeek: 1,
      startHour: 8,
      endHour: 17,
    },
    validationSchema,
    onSubmit: async (values) => {
      const newSlot: WorkingHoursSlot = {
        dayOfWeek: values.dayOfWeek,
        startHour: values.startHour,
        endHour: values.endHour,
        id: editingSlot?.id,
      };

      // Check for overlaps
      if (hasOverlap(newSlot, editingSlot?.id)) {
        formik.setFieldError('endHour', 'Ces heures se chevauchent avec un créneau existant');
        return;
      }

      try {
        if (editingSlot && editingSlot.id && employeeId && employeeId !== 'new') {
          // Update existing slot via API
          const slotId = editingSlot.id;
          const success = await updateWorkingHoursSlot(slotId, newSlot);
          if (success) {
            const updatedSlots = workingHours.map(slot =>
              slot.id === slotId ? { ...newSlot, id: slotId } : slot
            );
            onChange(updatedSlots);
            enqueueSnackbar('Créneau modifié avec succès', { variant: 'success' });
          }
        } else if (employeeId && employeeId !== 'new') {
          const createdSlot = await createWorkingHours({
            dayOfWeek: newSlot.dayOfWeek,
            startHour: newSlot.startHour,
            endHour: newSlot.endHour,
            employeeId: employeeId,
          });
          if (createdSlot) {
            const newSlotWithId = { ...newSlot, id: createdSlot.id };
            onChange([...workingHours, newSlotWithId]);
            enqueueSnackbar('Créneau ajouté avec succès', { variant: 'success' });
          }
        } else {

          if (editingSlot) {
            const updatedSlots = workingHours.map(slot =>
              slot.id === editingSlot.id ? newSlot : slot
            );
            onChange(updatedSlots);
          } else {
            onChange([...workingHours, newSlot]);
          }
          enqueueSnackbar('Créneau ajouté (sera sauvegardé avec l\'employé)', { variant: 'info' });
        }

        handleCloseDialog();
      } catch (error: any) {
        console.error('Error saving working hours slot:', error);
        enqueueSnackbar('Erreur lors de la sauvegarde du créneau', { variant: 'error' });
      }
    },
  });

  const handleAddSlot = () => {
    setEditingSlot(null);
    formik.resetForm();
    setIsDialogOpen(true);
  };

  const handleEditSlot = (slot: WorkingHoursSlot) => {
    setEditingSlot(slot);
    formik.setValues({
      dayOfWeek: slot.dayOfWeek,
      startHour: slot.startHour,
      endHour: slot.endHour,
    });
    setIsDialogOpen(true);
  };

  const handleDeleteSlot = async (slotToDelete: WorkingHoursSlot) => {
    try {
      if (slotToDelete.id && employeeId && employeeId !== 'new') {
        // Delete via API
        const success = await deleteWorkingHoursSlot(slotToDelete.id);
        if (success) {
          const updatedSlots = workingHours.filter(slot => slot.id !== slotToDelete.id);
          onChange(updatedSlots);
        }
      } else {
        // Fallback: just update local state
        const updatedSlots = workingHours.filter(slot => slot.id !== slotToDelete.id);
        onChange(updatedSlots);
        enqueueSnackbar('Créneau supprimé (sera sauvegardé avec l\'employé)', { variant: 'info' });
      }
    } catch (error: any) {
      console.error('Error deleting working hours slot:', error);
      enqueueSnackbar('Erreur lors de la suppression du créneau', { variant: 'error' });
    }
  };

  const handleCloseDialog = () => {
    setIsDialogOpen(false);
    setEditingSlot(null);
    formik.resetForm();
  };

  const formatTimeRange = (startHour: number, endHour: number) => {
    return `${formatTime(startHour)} - ${formatTime(endHour)}`;
  };

  return (
    <Box>
      <Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 2 }}>
        <Typography variant="h6" color="primary">
          Disponibilité
        </Typography>
        <Button
          variant="outlined"
          startIcon={<AddIcon />}
          onClick={handleAddSlot}
          disabled={disabled}
          size="small"
        >
          Ajouter un créneau
        </Button>
      </Box>

      {/* Working Hours Grid */}
      <Grid container spacing={1}>
        {Object.entries(DAY_NAMES).map(([dayNum, dayName]) => {
          const dayNumber = parseInt(dayNum);
          const daySlots = workingHoursByDay[dayNumber] || [];

          return (
            <Grid item xs={12} sm={6} md={4} key={dayNumber}>
              <Box
                sx={{
                  border: '1px solid',
                  borderColor: 'divider',
                  borderRadius: 1,
                  p: 1,
                  minHeight: 120,
                }}
              >
                <Typography
                  variant="subtitle2"
                  sx={{
                    fontWeight: 'bold',
                    mb: 1,
                    textAlign: 'center',
                    color: 'primary.main',
                  }}
                >
                  {dayName}
                </Typography>

                <ConditionalComponent isValid={daySlots.length === 0}>
                  <Typography
                    variant="caption"
                    color="text.secondary"
                    sx={{ textAlign: 'center', display: 'block' }}
                  >
                    Aucun créneau
                  </Typography>
                </ConditionalComponent>

                <ConditionalComponent isValid={daySlots.length > 0}>
                  <Box sx={{ display: 'flex', flexDirection: 'column', gap: 0.5 }}>
                    {daySlots.map((slot, index) => (
                      <Box
                        key={slot.id || index}
                        sx={{
                          display: 'flex',
                          alignItems: 'center',
                          justifyContent: 'space-between',
                          gap: 0.5,
                        }}
                      >
                        <Chip
                          label={formatTimeRange(slot.startHour, slot.endHour)}
                          size="small"
                          color="primary"
                          variant="outlined"
                          sx={{ flex: 1, fontSize: '0.75rem' }}
                        />
                        <ConditionalComponent isValid={!disabled}>
                          <>
                            <Tooltip title="Modifier">
                              <IconButton
                                size="small"
                                onClick={() => handleEditSlot(slot)}
                                disabled={updating}
                              >
                                <EditIcon fontSize="small" />
                              </IconButton>
                            </Tooltip>
                            <Tooltip title="Supprimer">
                              <IconButton
                                size="small"
                                onClick={() => handleDeleteSlot(slot)}
                                color="error"
                                disabled={deleting}
                              >
                                <DeleteIcon fontSize="small" />
                              </IconButton>
                            </Tooltip>
                          </>
                        </ConditionalComponent>
                      </Box>
                    ))}
                  </Box>
                </ConditionalComponent>
              </Box>
            </Grid>
          );
        })}
      </Grid>

      {/* Add/Edit Dialog */}
      <Dialog open={isDialogOpen} onClose={handleCloseDialog} maxWidth="sm" fullWidth>
        <DialogTitle>
          {editingSlot ? 'Modifier le créneau' : 'Ajouter un créneau'}
        </DialogTitle>
        <form onSubmit={formik.handleSubmit}>
          <DialogContent>
            <Grid container spacing={2} sx={{ mt: 1 }}>
              <Grid item xs={12}>
                <FormControl fullWidth error={formik.touched.dayOfWeek && Boolean(formik.errors.dayOfWeek)}>
                  <InputLabel>Jour</InputLabel>
                  <Select
                    name="dayOfWeek"
                    value={formik.values.dayOfWeek}
                    onChange={formik.handleChange}
                    label="Jour"
                  >
                    {Object.entries(DAY_NAMES).map(([dayNum, dayName]) => (
                      <MenuItem key={dayNum} value={parseInt(dayNum)}>
                        {dayName}
                      </MenuItem>
                    ))}
                  </Select>
                </FormControl>
              </Grid>

              <Grid item xs={6}>
                <FormControl fullWidth error={formik.touched.startHour && Boolean(formik.errors.startHour)}>
                  <InputLabel>Heure de début</InputLabel>
                  <Select
                    name="startHour"
                    value={formik.values.startHour}
                    onChange={formik.handleChange}
                    label="Heure de début"
                  >
                    {TIME_SLOTS.map(hour => (
                      <MenuItem key={hour} value={hour}>
                        {formatTime(hour)}
                      </MenuItem>
                    ))}
                  </Select>
                </FormControl>
              </Grid>

              <Grid item xs={6}>
                <FormControl fullWidth error={formik.touched.endHour && Boolean(formik.errors.endHour)}>
                  <InputLabel>Heure de fin</InputLabel>
                  <Select
                    name="endHour"
                    value={formik.values.endHour}
                    onChange={formik.handleChange}
                    label="Heure de fin"
                  >
                    {TIME_SLOTS.map(hour => (
                      <MenuItem key={hour} value={hour}>
                        {formatTime(hour)}
                      </MenuItem>
                    ))}
                  </Select>
                </FormControl>
              </Grid>
            </Grid>

            <ConditionalComponent isValid={!!(formik.errors.endHour && formik.touched.endHour)}>
              <Alert severity="error" sx={{ mt: 2 }}>
                {formik.errors.endHour}
              </Alert>
            </ConditionalComponent>
          </DialogContent>

          <DialogActions>
            <Button onClick={handleCloseDialog} disabled={creating || updating}>
              Annuler
            </Button>
            <Button
              type="submit"
              variant="contained"
              disabled={creating || updating}
            >
              {creating || updating ? 'Sauvegarde...' : (editingSlot ? 'Modifier' : 'Ajouter')}
            </Button>
          </DialogActions>
        </form>
      </Dialog>
    </Box>
  );
}

