'use client';

import { useState, useCallback, useEffect, Dispatch, SetStateAction } from 'react';
import { CircularProgress, Grid, Typography } from '@mui/material';
import type { FormFieldType } from '@/shared/types/common';
import DuplicableField from '@/shared/components/form/duplicable-field';
import { getLabel } from '@/shared/_mock';
import { type FieldType, useMultipleFields } from '@/hooks/use-multiple-fields';
import TransportScheduleField from './transport-schedule-field';
import type { DaysOfWeek, WeekType } from '@/shared/types/passenger';
import type { PeriodOfDay } from '@/shared/types/ammendment-passenger';
import type { IBaseEntity } from '@/shared/types/client';

export interface DaySchedule extends IBaseEntity {
  dayOfWeek: DaysOfWeek;
  periodOfDay: PeriodOfDay;
}

export interface WeekSchedule extends IBaseEntity {
  weekType: WeekType;
  schedules: DaySchedule[];
}

export interface EstablishmentSchedule extends IBaseEntity {
  idEstablishment: number;
  establishmentName: string;
  dayScheduleEstablishments: WeekSchedule[];
}

const getDefaultSchedule = (): EstablishmentSchedule => ({
  id: '',
  idEstablishment: 0,
  establishmentName: '',
  dayScheduleEstablishments: [],
});

interface EtablissementJoursFieldProps {
  field: FormFieldType<any>;
  values: {
    establishmentTransportSchedules: EstablishmentSchedule[];
  };
  errors: (index: number) => string | undefined;
  isReadOnly: boolean;
  etablissementsOptions: { value: string; label: string }[];
  onFieldChange: (field: string, value: any) => void;
  handleFieldBlur: (index: number) => void;
  onAddEstablishment?: () => void;
  setSharedSchedules?: Dispatch<SetStateAction<WeekSchedule[]>>;
  mode?: string;
}

export default function EtablissementJoursField({
  field,
  values,
  errors,
  isReadOnly,
  etablissementsOptions,
  onFieldChange,
  handleFieldBlur,
  onAddEstablishment,
  setSharedSchedules,
  mode,
}: EtablissementJoursFieldProps) {
  const [establishmentSchedules, setEstablishmentSchedules] = useState<EstablishmentSchedule[]>(
    values?.establishmentTransportSchedules.length > 0
      ? values?.establishmentTransportSchedules
      : [getDefaultSchedule()]
  );

  const { fields, handleAdd, handleDelete, handleChange, reset } = useMultipleFields({
    initialValues: {
      etablissement: establishmentSchedules.map(
        (schedule) => schedule?.idEstablishment?.toString() || ''
      ),
    },
    onChange: (type, newValues) => {
      if (type === 'etablissement') {
        try {
          const updatedSchedules = newValues.map((establishmentId: string, index: number) => {
            const existingSchedule = establishmentSchedules[index] || getDefaultSchedule();

            const establishment = etablissementsOptions.find(
              (opt) => opt.value === establishmentId
            );

            return {
              ...existingSchedule,
              idEstablishment: Number.parseInt(establishmentId) || 0,
              establishmentName: establishment?.label || '',
            };
          });

          setEstablishmentSchedules(updatedSchedules);
          onFieldChange('establishmentTransportSchedules', updatedSchedules);
        } catch (error) {
          console.error('Error in onChange:', error);
        }
      }
    },
    isReadOnly,
  });

  useEffect(() => {
    if (values?.establishmentTransportSchedules?.length === 0) {
      setEstablishmentSchedules([getDefaultSchedule()]);
      reset({ etablissement: [''] });
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [values?.establishmentTransportSchedules]);

  const handleAddEtablissement = useCallback(() => {
    try {
      const newSchedule = getDefaultSchedule();

      const updatedSchedules = [...establishmentSchedules, newSchedule];
      setEstablishmentSchedules(updatedSchedules);
      handleAdd('etablissement');
      onFieldChange('establishmentTransportSchedules', updatedSchedules);
    } catch (error) {
      console.error('Error in handleAddEtablissement:', error);
    }
  }, [establishmentSchedules, handleAdd, onFieldChange]);

  const handleDeleteEtablissement = useCallback(
    (type: FieldType, index: number) => {
      try {
        const updatedSchedules = establishmentSchedules.filter((_, i) => i !== index);
        setEstablishmentSchedules(updatedSchedules);
        onFieldChange('establishmentTransportSchedules', updatedSchedules);
        handleDelete('etablissement', index);
      } catch (error) {
        console.error('Error in handleDeleteEtablissement:', error);
      }
    },
    [establishmentSchedules, onFieldChange, handleDelete]
  );

  const handleScheduleChange = useCallback(
    (index: number, updatedSchedules: WeekSchedule[]) => {
      try {
        const updatedEstablishmentSchedules = establishmentSchedules.map((schedule, idx) => {
          if (idx === index) {
            return {
              ...schedule,
              dayScheduleEstablishments: updatedSchedules,
            };
          }
          return schedule;
        });

        setEstablishmentSchedules(updatedEstablishmentSchedules);
        onFieldChange('establishmentTransportSchedules', updatedEstablishmentSchedules);
      } catch (error) {
        console.error('Error in handleScheduleChange:', error);
      }
    },
    [establishmentSchedules, onFieldChange]
  );

  if (!fields || !fields.etablissement) {
    return <CircularProgress />;
  }

  return (
    <>
      {fields.etablissement.map((value, index) => (
        <>
          <DuplicableField
            formData={values}
            key={`etablissement-${index}`}
            fieldType={'etablissement'}
            field={field}
            index={index}
            value={value}
            isReadOnly={isReadOnly}
            onChange={handleChange}
            onAdd={handleAddEtablissement}
            onDelete={handleDeleteEtablissement}
            onAddEstablishment={onAddEstablishment}
            sx={{ mt: 3 }}
            error={errors(index)}
            onBlur={() => handleFieldBlur(index)}
          />
          <Grid
            item
            xs={12}
            md={5}
            sx={{
              '@media (min-width: 1850px)': {
                flexBasis: '33.333%',
                maxWidth: '33.333%',
              },
            }}
            key={`jours-${index}`}
          >
            <Typography sx={{ color: (theme) => theme.palette.primary.main }}>
              {`Jours (${getLabel(value, etablissementsOptions) || `Établissement ${index + 1}`})`}
            </Typography>
            <TransportScheduleField
              index={index}
              mode={mode}
              setSharedSchedules={setSharedSchedules as Dispatch<SetStateAction<WeekSchedule[]>>}
              initialSchedules={establishmentSchedules[index]?.dayScheduleEstablishments || []}
              otherSchedules={establishmentSchedules
                .filter((_, idx) => idx !== index)
                .map((schedule) => schedule?.dayScheduleEstablishments || [])}
              onChange={(updatedSchedules) => handleScheduleChange(index, updatedSchedules)}
              isReadOnly={isReadOnly}
            />
          </Grid>
        </>
      ))}
    </>
  );
}
