'use client';

import React, { useEffect, useState } from 'react';
import {
  Dialog,
  DialogTitle,
  DialogContent,
  DialogActions,
  Button,
  FormControl,
  Stack,
  Box,
  FormControlLabel,
  Radio,
  Typography,
  IconButton,
} from '@mui/material';
import { LocalizationProvider } from '@mui/x-date-pickers';
import { StyledRadioGroup, StyledTextField } from '@/shared/theme/css';

import dayjs, { Dayjs } from 'dayjs';
import isSameOrAfter from 'dayjs/plugin/isSameOrAfter';
dayjs.extend(isSameOrAfter);

import { IActiveDriver } from '@/shared/types/driver';
import { _drivers } from '@/shared/_mock/_drivers';
import ConditionalComponent from '@/shared/components/table/ConditionalComponent';
import { useRoadMapStore } from '@/shared/api/stores/roadMapStore';
import * as Yup from 'yup';
import { useFormik } from 'formik';
import { ManualRoadMapCreationResult } from '../invalid-roadmap-dialog';
import { enqueueSnackbar } from 'notistack';
import { useDriverStore } from '@/shared/api/stores/driverStore';
import { SendRoadMapPlanningFormValues } from '@/shared/types/roadMap';
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
import { fr } from 'date-fns/locale';
import DriverSelector from './driver-selector';
import ActionButtons from '@/shared/components/form/buttons-action';
import WeeklyFormSection from './weekly-form-section';
import SingleDayFormSection from './single-day-form-section';
import DailyFormSection from './daily-form-section';
import CloseIcon from '@mui/icons-material/Close';
import DepartmentSelectorAutocomplete from './department-selector';

type SendPlanningDialogProps = {
  open: boolean;
  onClose: () => void;
  onSend: (data: any) => void;
  drivers: IActiveDriver[];
};

const validationSchema = Yup.object().shape({
  title: Yup.string().required('Le titre est requis'),

  sendDate: Yup.date()
    .nullable()
    .when('mode', {
      is: (mode: string) => mode === 'quotidienne' || mode === 'hebdomadaire',
      then: (schema) => schema.required("La date d'envoi est requise"),
      otherwise: (schema) => schema,
    })
    .test('is-today-or-future', "La date d'envoi ne peut pas être dans le passé", function (value) {
      if (!value) return true;
      return dayjs(value).startOf('day').isSameOrAfter(dayjs().startOf('day'));
    }),

  sendHour: Yup.date()
    .nullable()
    .required("L'heure d'envoi est requise")
    .test('is-hour-valid', "L'heure doit être au moins après l'heure actuelle", function (value) {
      const { mode, sendDate, startDate } = this.parent;
      if (!value) return false;

      if (mode === 'journee') {
        if (!startDate) return false;
        const isToday = dayjs(startDate).isSame(dayjs(), 'day');
        if (isToday) {
          return dayjs(value).isSameOrAfter(dayjs());
        } else {
          return true;
        }
      } else {
        if (!sendDate) return false;
        const isToday = dayjs(sendDate).isSame(dayjs(), 'day');
        if (isToday) {
          return dayjs(value).isSameOrAfter(dayjs());
        } else {
          return true;
        }
      }
    }),

  startDate: Yup.date()
    .nullable()
    .required('La date de début est requise')
    .test(
      'is-after-sendDate',
      "La date de début doit être au moins le lendemain de la date d'envoi",
      function (value) {
        const { sendDate } = this.parent;
        if (!value || !sendDate) return true;

        return dayjs(value)
          .startOf('day')
          .isSameOrAfter(dayjs(sendDate).add(1, 'day').startOf('day'));
      }
    ),

  endDate: Yup.date()
    .nullable()
    .test(
      'is-after-startDate',
      'La date de fin doit être après la date de début',
      function (value) {
        const { startDate } = this.parent;
        if (!value || !startDate) return true;

        return dayjs(value).isAfter(dayjs(startDate));
      }
    ),

  planningDate: Yup.date()
    .nullable()
    .when('planningDayOption', {
      is: 'specific',
      then: (schema) =>
        schema
          .test(
            'is-tomorrow-or-future',
            "La date de planning doit être  au moins le lendemain de la date d'envoi",
            (value) =>
              !value ||
              dayjs(value).startOf('day').isSameOrAfter(dayjs().add(1, 'day').startOf('day'))
          )
          .required('La date de planning est requise'),
    }),

  planningDayOption: Yup.string().oneOf(['same', 'next', 'specific']),

  dayOfWeek: Yup.string().when('mode', {
    is: 'hebdomadaire',
    then: (schema) => schema.required("Le jour d'envoi est requis"),
  }),

  mode: Yup.string().required(),

  selectedDrivers: Yup.array()
    .of(Yup.object())
    .min(1, 'Au moins un chauffeur doit être sélectionné')
    .required('La sélection des chauffeurs est requise'),
});

export default function SendPlanningDialog({
  open,
  onClose,
  onSend,
  drivers,
}: SendPlanningDialogProps) {
  const initialValues: SendRoadMapPlanningFormValues = {
    sendDate: null as Dayjs | Date | null,
    startDate: null as Dayjs | Date | null,
    selectedDrivers: [] as IActiveDriver[],
    title: '',
    endDate: null as Dayjs | Date | null,
    sendHour: null,
    planningDayOption: 'same',
    planningDate: null as Dayjs | Date | null,
    dayOfWeek: 'Lundi',
    mode: 'quotidienne',
  };

  const handleModeChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    const value = event.target.value as 'quotidienne' | 'hebdomadaire' | 'journee';
    formik.setFieldValue('mode', value);
    formik.setFieldValue('sendDate', null);
    formik.setFieldValue('startDate', null);
    formik.setFieldValue('endDate', null);
    formik.setFieldValue('sendHour', null);
    formik.setFieldValue('planningDate', null);
    formik.setFieldValue('planningDayOption', 'same');
  };

  const { schedulePlanning } = useRoadMapStore();
  const [selectedDepartments, setSelectedDepartments] = useState<string[]>([]);
  const [filteredDrivers, setFilteredDrivers] = useState<IActiveDriver[]>([]);
  const [departments, setDepartments] = useState<string[]>([]);
  const dayOfWeekMap: Record<string, string> = {
    LUNDI: 'MONDAY',
    MARDI: 'TUESDAY',
    MERCREDI: 'WEDNESDAY',
    JEUDI: 'THURSDAY',
    VENDREDI: 'FRIDAY',
    SAMEDI: 'SATURDAY',
    DIMANCHE: 'SUNDAY',
  };

  const preparePlanningRequest = (values: SendRoadMapPlanningFormValues) => {
    return {
      type: values.mode,
      title: values.title,
      sendDate: values.sendDate ? dayjs(values.sendDate).format('YYYY-MM-DD') : null,
      sendTime: values.sendHour ? dayjs(values.sendHour).format('HH:mm:ss') : null,
      planningDayOption: values.planningDayOption,
      planningDate: values.planningDate ? dayjs(values.planningDate).format('YYYY-MM-DD') : null,
      driverIds: values.selectedDrivers.map((driver) => driver.id),
      startDate: values.startDate ? dayjs(values.startDate).format('YYYY-MM-DD') : null,
      endDate: values.endDate ? dayjs(values.endDate).format('YYYY-MM-DD') : null,
      dayOfWeek: values.dayOfWeek ? dayOfWeekMap[values.dayOfWeek.toUpperCase()] : null,
    };
  };

  const formik = useFormik<SendRoadMapPlanningFormValues>({
    initialValues,
    validationSchema,
    onSubmit: async (values) => {
      const requestPayload = preparePlanningRequest(values);
      await schedulePlanning(requestPayload);
     onSend(requestPayload);
      handleCancel();
      enqueueSnackbar('Le planning a été programmé avec succès.', { variant: 'success' });
    },
  });

  const [activeDrivers, setActiveDrivers] = useState<IActiveDriver[]>([]);
  const { getActiveDrivers } = useDriverStore();

  useEffect(() => {
    if (open) {
      getActiveDrivers().then((drivers) => {
        setActiveDrivers(drivers);
        const uniqueDepartments = Array.from(new Set(drivers.map((d) => d.departmentName)));
        setDepartments(uniqueDepartments);
      });
    }
  }, [open]);

  useEffect(() => {
    if (selectedDepartments.length > 0) {
      const driversFromDept = activeDrivers.filter((d) =>
        selectedDepartments.includes(d.departmentName)
      );

      if (formik.values.selectedDrivers.length === 0) {
        setFilteredDrivers(driversFromDept);
        formik.setFieldValue('selectedDrivers', driversFromDept);
      } else {
        const currentSelected = formik.values.selectedDrivers;

        const selectedIds = new Set(currentSelected.map((d) => d.id));

        const driversToAdd = driversFromDept.filter((d) => !selectedIds.has(d.id));

        const newSelectedDrivers = [...currentSelected, ...driversToAdd];

        setFilteredDrivers(driversFromDept);
        formik.setFieldValue('selectedDrivers', newSelectedDrivers);
      }
    } else {
      setFilteredDrivers(activeDrivers);
      formik.setFieldValue('selectedDrivers', []);
    }
  }, [selectedDepartments, activeDrivers]);
  const handleCancel = () => {
    formik.resetForm();
    setSelectedDepartments([]);
    setFilteredDrivers([]);

    onClose();
  };
  return (
    <Dialog open={open} onClose={onClose} fullWidth maxWidth="sm">
      <form onSubmit={formik.handleSubmit}>
        <Box sx={{ bgcolor: 'primary.main' }}>
          <DialogTitle sx={{ color: 'white', position: 'relative' }}>
            Envoi de nouvelle feuille de route
            <IconButton
              aria-label="close"
              onClick={handleCancel}
              sx={{
                position: 'absolute',
                right: 8,
                top: 8,
                color: 'white',
              }}
            >
              <CloseIcon />
            </IconButton>
          </DialogTitle>
        </Box>
        <DialogContent>
          <Stack spacing={2} mt={1}>
            <StyledTextField
              name="title"
              label="Titre d'envoi"
              fullWidth
              required
              value={formik.values.title}
              onChange={formik.handleChange}
              error={!!(formik.touched.title && formik.errors.title)}
              helperText={formik.touched.title && formik.errors.title}
            />

            <FormControl fullWidth>
              <LocalizationProvider dateAdapter={AdapterDateFns} adapterLocale={fr}>
                <Typography variant="subtitle2" sx={{ fontWeight: 'bold' }}>
                  Type d&apos;envoi
                </Typography>
                <StyledRadioGroup
                  value={formik.values.mode}
                  onChange={handleModeChange}
                  sx={{ display: 'flex', justifyContent: 'space-between', width: '100%' }}
                >
                  <FormControlLabel
                    value="journee"
                    control={<Radio />}
                    label="Journée"
                    sx={{ flex: 1, margin: 0 }}
                  />
                  <FormControlLabel
                    value="quotidienne"
                    control={<Radio />}
                    label="Quotidienne"
                    sx={{ flex: 1, margin: 0 }}
                  />
                </StyledRadioGroup>

                <Stack spacing={2} mt={2}>
                  {/* DÉMARRAGE + HEURE JOURNÉE */}
                  <ConditionalComponent isValid={formik.values.mode === 'journee'}>
                    <SingleDayFormSection formik={formik} />
                  </ConditionalComponent>
                  {/* QUOTIDIENNE */}
                  <ConditionalComponent isValid={formik.values.mode === 'quotidienne'}>
                    <DailyFormSection formik={formik} />
                  </ConditionalComponent>

                  {/* HEBDOMADAIRE */}
                  <ConditionalComponent isValid={formik.values.mode === 'hebdomadaire'}>
                    <WeeklyFormSection formik={formik} />
                  </ConditionalComponent>

                  <DepartmentSelectorAutocomplete
                    departments={departments}
                    selectedDepartments={selectedDepartments}
                    setSelectedDepartments={setSelectedDepartments}
                  />

                  <Box>
                    <DriverSelector
                      drivers={filteredDrivers}
                      selectedDrivers={formik.values.selectedDrivers}
                      setSelectedDrivers={(drivers) => {
                        formik.setFieldValue('selectedDrivers', drivers);
                      }}
                    />
                    <ConditionalComponent
                      isValid={!!(formik.touched.selectedDrivers && formik.errors.selectedDrivers)}
                    >
                      <Typography sx={{ ml: 2 }} color="error" variant="caption">
                        {formik.errors.selectedDrivers as string}
                      </Typography>
                    </ConditionalComponent>
                  </Box>
                </Stack>
              </LocalizationProvider>
            </FormControl>
          </Stack>
        </DialogContent>
        <DialogActions>
          <ActionButtons
            onSave={formik.handleSubmit}
            onCancel={handleCancel}
            secoundButtonText="Envoyer"
          />
        </DialogActions>
      </form>
    </Dialog>
  );
}
