'use client';

import { useEffect, useState, useMemo } from 'react';
import { Typography, Grid, IconButton, Button } from '@mui/material';
import FontAwesome from '../../../../../components/fontawesome/fontawesome';
import { faClock, faCopy, faPlus, faRotateRight, faTimes } from '@fortawesome/free-solid-svg-icons';
import { alpha, Box } from '@mui/system';
import { StyledTimePicker } from '@/shared/theme/css';
import CustomTooltip from '@/shared/components/tooltips/tooltip-custom';
import { LocalizationProvider } from '@mui/x-date-pickers';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import dayjs from 'dayjs';
import 'dayjs/locale/fr';
import { DAYS } from '@/shared/_mock/_usagers';
import type { TimeValue } from '@/shared/types/usager';
import { MOCKED_SCHEDULE_DATA } from '@/shared/_mock/_avenants';
import ConditionalComponent from '@/shared/components/table/ConditionalComponent';
import type { ScheduleDTO } from '@/shared/types/amendment';
import ActionButtons from '@/shared/components/form/buttons-action';
import type { ModeType } from '@/shared/types/common';
import { useFormikContext } from 'formik';
import type {
  FormikAmendmentPassengerDetails,
  HorairesSpecifiqueTabsProps,
  WeeklyScheduleType,
  WeekScheduleProps,
} from './types/formik-types';
import { deepCloneSchedules, mapSchedulesToWeeklySchedule } from './utils/converters';
import { FormikAmendmentCircuitDetails } from '@/shared/sections/circuit/components/circuit-form/avenant/components/avenant-horaire';

dayjs.locale('fr');

const CustomTimeIcon = () => <FontAwesome icon={faClock} sx={{ color: 'primary.main' }} />;

function WeekSchedule({
  type,
  values,
  onChange,
  onAddField,
  onRemoveField,
  onCopy,
  onReset,
  isReadOnly,
}: WeekScheduleProps) {
  return (
    <Grid spacing={6} sx={{ mx: '5%', mt: 4 }}>
      <Box sx={{ display: 'flex', gap: 1 }}>
        <Typography
          variant="h5"
          sx={{
            color: 'primary.main',
            fontWeight: (theme) => theme.typography.fontWeightBold,
          }}
        >
          {`Semaine ${type === 'pair' ? 'paire' : 'impaire'}`}
        </Typography>
        <CustomTooltip title="Dupliquer la semaine" arrow>
          <span>
            <IconButton onClick={onCopy} size="small" disabled={isReadOnly}>
              <FontAwesome color={'primary.main'} icon={faCopy} width={18} />
            </IconButton>
          </span>
        </CustomTooltip>
      </Box>

      <Grid container spacing={'5%'}>
        {(['morning', 'evening'] as const).map((period) => (
          <Grid item xs={12} md={6} key={period}>
            <Box sx={{ mb: 2, display: 'flex', alignItems: 'center', gap: 1 }}>
              <Typography variant="h6" color={(theme) => alpha(theme.palette.text.secondary, 0.8)}>
                {period === 'morning' ? 'Matin' : 'Soir'}
              </Typography>
              <CustomTooltip
                title={`Réinitialiser le ${period === 'morning' ? 'matin' : 'soir'}`}
                arrow
              >
                <span>
                  <IconButton onClick={() => onReset(period)} size="small" disabled={isReadOnly}>
                    <FontAwesome
                      color={(theme) => alpha(theme.palette.text.secondary, 0.8)}
                      icon={faRotateRight}
                      width={18}
                    />
                  </IconButton>
                </span>
              </CustomTooltip>
            </Box>
            {DAYS.map((day) => {
              const dayKey = day.toLowerCase();
              const periodData = values[dayKey]?.[period];

              return (
                <Box
                  key={`${dayKey}-${period}`}
                  sx={{ mb: !periodData?.retour && period === 'morning' ? '3.1px' : 4 }}
                >
                  <ConditionalComponent
                    isValid={period === 'morning'}
                    defaultComponent={
                      <Box
                        sx={{
                          display: periodData?.aller ? 'flex' : 'block',
                          gap: 1,
                          width: '100%',
                        }}
                      >
                        <ConditionalComponent isValid={!!periodData?.aller}>
                          <LocalizationProvider dateAdapter={AdapterDayjs}>
                            <StyledTimePicker
                              label={day + ' (Aller)'}
                              value={periodData?.aller}
                              onChange={(v) => onChange(dayKey, period, 'aller', v)}
                              disabled={isReadOnly}
                              slots={{ openPickerIcon: CustomTimeIcon }}
                              slotProps={{
                                textField: { fullWidth: true, placeholder: "Sélectionner l'heure" },
                              }}
                              views={['hours', 'minutes']}
                              format="HH:mm"
                            />
                          </LocalizationProvider>
                        </ConditionalComponent>

                        <LocalizationProvider dateAdapter={AdapterDayjs}>
                          <StyledTimePicker
                            label={day + ' (Retour)'}
                            value={periodData?.retour || null}
                            onChange={(v) => onChange(dayKey, period, 'retour', v)}
                            disabled={isReadOnly}
                            slots={{ openPickerIcon: CustomTimeIcon }}
                            slotProps={{
                              textField: { fullWidth: true, placeholder: "Sélectionner l'heure" },
                            }}
                            views={['hours', 'minutes']}
                            format="HH:mm"
                          />
                        </LocalizationProvider>
                      </Box>
                    }
                  >
                    <Box
                      sx={{ display: periodData?.retour ? 'flex' : 'block', gap: 1, width: '100%' }}
                    >
                      <Box sx={{ flex: 1 }}>
                        <LocalizationProvider dateAdapter={AdapterDayjs}>
                          <StyledTimePicker
                            label={day + ' (Aller)'}
                            value={periodData?.aller || null}
                            onChange={(v) => onChange(dayKey, period, 'aller', v)}
                            disabled={isReadOnly}
                            slots={{ openPickerIcon: CustomTimeIcon }}
                            slotProps={{
                              textField: { fullWidth: true, placeholder: "Sélectionner l'heure" },
                            }}
                            views={['hours', 'minutes']}
                            format="HH:mm"
                          />
                        </LocalizationProvider>
                        <ConditionalComponent isValid={!periodData?.retour}>
                          <Button
                            disabled={isReadOnly}
                            startIcon={<FontAwesome width={14} icon={faPlus} />}
                            onClick={(e) => {
                              e.preventDefault();
                              e.stopPropagation();
                              onAddField(dayKey, period, 'retour');
                            }}
                            sx={{ color: (theme) => theme.palette.primary.main, fontSize: '12px' }}
                            size="small"
                          >
                            Ajouter retour
                          </Button>
                        </ConditionalComponent>
                      </Box>

                      <ConditionalComponent isValid={!!periodData?.retour}>
                        <Box sx={{ display: 'flex', gap: 1, flex: 1, alignItems: 'center' }}>
                          <LocalizationProvider dateAdapter={AdapterDayjs}>
                            <StyledTimePicker
                              label={day + ' (Retour)'}
                              value={periodData?.retour}
                              onChange={(v) => onChange(dayKey, period, 'retour', v)}
                              disabled={isReadOnly}
                              slots={{ openPickerIcon: CustomTimeIcon }}
                              slotProps={{
                                textField: { fullWidth: true, placeholder: "Sélectionner l'heure" },
                              }}
                              views={['hours', 'minutes']}
                              format="HH:mm"
                            />
                          </LocalizationProvider>
                          <CustomTooltip title="Supprimer le retour" arrow>
                            <span>
                              <IconButton
                                onClick={(e) => {
                                  e.preventDefault();
                                  e.stopPropagation();
                                  onRemoveField(dayKey, period, 'retour');
                                }}
                                disabled={isReadOnly}
                                sx={{ color: (theme) => theme.palette.error.main, p: 0 }}
                              >
                                <FontAwesome icon={faTimes} />
                              </IconButton>
                            </span>
                          </CustomTooltip>
                        </Box>
                      </ConditionalComponent>
                    </Box>
                  </ConditionalComponent>
                </Box>
              );
            })}
          </Grid>
        ))}
      </Grid>
    </Grid>
  );
}

function useFormikContextSafe() {
  const context = useFormikContext<
    FormikAmendmentPassengerDetails | FormikAmendmentCircuitDetails
  >();
  return context || null;
}

export default function HorairesSpecifiqueTabs({
  mode,
  title,
  withData,
  schedules,
  useFormik = false,
  isGenerated = true,
}: HorairesSpecifiqueTabsProps) {
  const [localSelectedDays, setLocalSelectedDays] = useState<WeeklyScheduleType>({
    pair: {},
    impair: {},
  });

  const formikContext = useFormikContextSafe();
  const isReadOnly = mode === 'view' || (mode === 'edit' && isGenerated);

  const shouldUseFormik = useMemo(() => {
    return useFormik && formikContext !== null;
  }, [useFormik, formikContext]);

  const selectedDays = useMemo(() => {
    if (shouldUseFormik && formikContext) {
      return formikContext.values.weeklySchedules;
    }
    return localSelectedDays;
  }, [shouldUseFormik, formikContext, localSelectedDays]);

  const updateSelectedDays = (newSchedules: WeeklyScheduleType) => {
    if (shouldUseFormik && formikContext) {
      formikContext.setFieldValue('weeklySchedules', newSchedules);
    } else {
      setLocalSelectedDays(newSchedules);
    }
  };

  useEffect(() => {
    if (withData) {
      let initialData: WeeklyScheduleType;

      if (schedules) {
        initialData = mapSchedulesToWeeklySchedule(schedules);
      } else if (shouldUseFormik && formikContext) {
        return;
      } else {
        initialData = MOCKED_SCHEDULE_DATA;
      }

      if (!shouldUseFormik) {
        setLocalSelectedDays(initialData);
      }
    }
  }, [withData, schedules, shouldUseFormik, formikContext]);

  const handleChange = (
    weekType: 'pair' | 'impair',
    day: string,
    period: 'morning' | 'evening',
    type: 'aller' | 'retour',
    value: TimeValue
  ) => {
    const newSchedules = {
      ...selectedDays,
      [weekType]: {
        ...selectedDays[weekType],
        [day]: {
          ...(selectedDays[weekType][day] || {
            morning: { aller: null },
            evening: { retour: null },
          }),
          [period]: {
            ...(selectedDays[weekType][day]?.[period] || {}),
            [type]: value,
          },
        },
      },
    };

    updateSelectedDays(newSchedules);
  };

  const handleAddField = (
    weekType: 'pair' | 'impair',
    day: string,
    period: 'morning' | 'evening',
    field: 'aller' | 'retour'
  ) => {
    const defaultTime = dayjs().hour(12).minute(0).second(0);
    const eveningAllerTime = dayjs().hour(14).minute(0).second(0);

    const currentDayData = selectedDays[weekType][day] || {
      morning: { aller: null },
      evening: { retour: null },
    };

    let newDayData = { ...currentDayData };

    newDayData = {
      ...newDayData,
      [period]: {
        ...newDayData[period],
        [field]: defaultTime,
      },
    };

    if (period === 'morning' && field === 'retour') {
      newDayData = {
        ...newDayData,
        evening: {
          ...newDayData.evening,
          aller: eveningAllerTime,
        },
      };
    }

    const newSchedules = {
      ...selectedDays,
      [weekType]: {
        ...selectedDays[weekType],
        [day]: newDayData,
      },
    };

    updateSelectedDays(newSchedules);
  };

  const handleCopy = (fromType: 'pair' | 'impair') => {
    const newSchedules = {
      ...selectedDays,
      [fromType === 'pair' ? 'impair' : 'pair']: deepCloneSchedules(selectedDays[fromType]),
    };

    updateSelectedDays(newSchedules);
  };

  const handleReset = (weekType: 'pair' | 'impair', period: 'morning' | 'evening') => {
    const updatedDays = Object.entries(selectedDays[weekType]).reduce(
      (acc, [day, data]) => ({
        ...acc,
        [day]: {
          ...data,
          [period]:
            period === 'morning' ? { aller: null, retour: null } : { aller: null, retour: null },
        },
      }),
      {}
    );

    const newSchedules = {
      ...selectedDays,
      [weekType]: updatedDays,
    };

    updateSelectedDays(newSchedules);
  };

  const handleRemoveField = (
    weekType: 'pair' | 'impair',
    day: string,
    period: 'morning' | 'evening',
    field: 'aller' | 'retour'
  ) => {
    const currentDayData = selectedDays[weekType][day] || {
      morning: { aller: null },
      evening: { retour: null },
    };

    let newDayData = { ...currentDayData };

    newDayData = {
      ...newDayData,
      [period]: {
        ...newDayData[period],
        [field]: null,
      },
    };

    if (period === 'morning' && field === 'retour') {
      newDayData = {
        ...newDayData,
        evening: {
          ...newDayData.evening,
          aller: null,
        },
      };
    }

    if (period === 'evening' && field === 'aller') {
      newDayData = {
        ...newDayData,
        morning: {
          ...newDayData.morning,
          retour: null,
        },
      };
    }

    const newSchedules = {
      ...selectedDays,
      [weekType]: {
        ...selectedDays[weekType],
        [day]: newDayData,
      },
    };

    updateSelectedDays(newSchedules);
  };

  return (
    <Box>
      <Typography
        variant="h5"
        sx={{
          color: 'primary.main',
          fontWeight: 'bold',
          mb: 4,
        }}
      >
        {title}
      </Typography>
      <Box
        style={{
          display: 'flex',
          alignItems: 'center',
          gap: '4%',
        }}
      >
        <WeekSchedule
          type="pair"
          values={selectedDays.pair}
          onChange={(day, period, type, value) => handleChange('pair', day, period, type, value)}
          onAddField={(day, period, field) => handleAddField('pair', day, period, field)}
          onRemoveField={(day, period, field) => handleRemoveField('pair', day, period, field)}
          onCopy={() => handleCopy('pair')}
          onReset={(period) => handleReset('pair', period)}
          isReadOnly={isReadOnly}
        />

        <WeekSchedule
          type="impair"
          values={selectedDays.impair}
          onChange={(day, period, type, value) => handleChange('impair', day, period, type, value)}
          onAddField={(day, period, field) => handleAddField('impair', day, period, field)}
          onRemoveField={(day, period, field) => handleRemoveField('impair', day, period, field)}
          onCopy={() => handleCopy('impair')}
          onReset={(period) => handleReset('impair', period)}
          isReadOnly={isReadOnly}
        />
      </Box>

      <ConditionalComponent isValid={!isReadOnly && !!schedules}>
        <Grid item xs={12}>
          <ActionButtons onSave={() => void 0} onCancel={() => void 0} mode={mode} />
        </Grid>
      </ConditionalComponent>
    </Box>
  );
}
