'use client';

import React, { Dispatch, SetStateAction, use, useEffect, useMemo, useState } from 'react';
import { Box, Grid } from '@mui/material';
import { centerFlexColumn } from '@/shared/theme/css';
import { FormFieldType, ModeType, TableColumn, TableType } from '@/shared/types/common';
import ActionButtons from '@/shared/components/form/buttons-action';
import { getPassengerFormFields } from '../../utils/form-fields-usager';
import ScheduleTable, { ScheduleHoursDTO } from '@/shared/components/form/schedule-table';
import EditExportButtons from '@/shared/components/form/edit-export-buttons';
import AvatarUploader from '@/shared/components/form/avatar-uploader';
import ConditionalComponent from '@/shared/components/table/ConditionalComponent';
import { DaysOfWeek, IPassengerList } from '@/shared/types/passenger';
import { useInfrastructureStore } from '@/shared/api/stores/admin-service/infrastructureStore';
import EtablissementJoursField, {
  WeekSchedule,
  type EstablishmentSchedule,
} from '@/shared/components/form/etablissement-jours-field';
import { useFormikContext } from 'formik';
import { StyledCircularProgress } from '@/shared/components/form/style';
import { apiToComponentStructure, componentToApiStructure } from '../../utils/schedule-converters';
import { useEstablishmentOptions } from '../../hooks/use-establishment-options';

import { useEstablishmentStore } from '@/shared/api/stores/admin-service/establishmentStore';
import { enqueueSnackbar } from 'notistack';
import UpdateEstablishmentHoursModal from './usager-details/update-establishment-hours-modal';
import { EstablishmentHoursResponse } from '@/shared/types/establishment';
import { faPlus } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { RenderFieldOptions } from '../../view/usager-new-view';
import CreateEtablissementModal from '@/shared/components/dialog/create-etablissement-modal';
import CreateInfrastructureModal from '@/shared/components/dialog/create-infrastructure-modal';

interface UsagerTabContentProps {
  renderField: (
    field: FormFieldType<IPassengerList>,
    options?: RenderFieldOptions
  ) => React.ReactNode;
  usager: IPassengerList;
  onEdit: (updatedContract: IPassengerList) => void;
  handleSave: () => void;
  onClose: () => void;
  mode: ModeType;
  isUsagerAttachedToAmendment?: boolean;
  tableHead: TableColumn[];
  loading: boolean;
  setSharedSchedules?: Dispatch<SetStateAction<WeekSchedule[]>>;
}

export default function UsagerTabForm({
  renderField,
  usager,
  onEdit,
  handleSave,
  onClose,
  mode,
  tableHead,
  isUsagerAttachedToAmendment,
  loading,
  setSharedSchedules,
}: UsagerTabContentProps) {
  const isReadOnly = mode === 'view';
  const { searchEstablishments, establishmentOptions } = useEstablishmentOptions();
  const { departmentNames, fetchDepartmentNames } = useInfrastructureStore();
  const { getEstablishmentHoursById, establishmentHoursById, establishmentHoursLoading } =
    useEstablishmentStore();
  const formik = useFormikContext<IPassengerList>();
  const [departmentOptions, setDepartmentOptions] = useState<{ value: string; label: string }[]>(
    []
  );
  const [frontendSchedules, setFrontendSchedules] = useState<EstablishmentSchedule[]>([]);
  const [isSchedulesLoaded, setIsSchedulesLoaded] = useState(false);
  const [openEstablishmentModal, setOpenEstablishmentModal] = useState(false);
  const [openInfrastructureModal, setOpenInfrastructureModal] = useState(false);
  const handleAddEstablishment = () => setOpenEstablishmentModal(true);
  const handleCloseEstablishmentModal = () => setOpenEstablishmentModal(false);
  const handleAddInfrastructure = () => setOpenInfrastructureModal(true);
  const handleCloseInfrastructureModal = () => setOpenInfrastructureModal(false);

  const [establishmentHours, setEstablishmentHours] = useState<Map<number, any>>(new Map());
  const [modalOpen, setModalOpen] = useState(false);
  const [selectedEstablishment, setSelectedEstablishment] = useState<{
    id: number;
    name: string;
    hours: EstablishmentHoursResponse[];
  } | null>(null);

  useEffect(() => {
    setIsSchedulesLoaded(false);
    const convertedSchedules = apiToComponentStructure(
      formik.values.establishmentTransportSchedules
    );
    setFrontendSchedules(convertedSchedules);
    setIsSchedulesLoaded(true);
  }, [formik.values.establishmentTransportSchedules]);

  useEffect(() => {
    const fetchData = async () => {
      await fetchDepartmentNames();
    };

    fetchData();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  useEffect(() => {
    if (departmentNames.length > 0) {
      setDepartmentOptions(
        departmentNames.map((department) => ({
          value: department.id.toString(),
          label: department.name,
        }))
      );
    }
  }, [departmentNames]);

  useEffect(() => {
    const fetchEstablishmentHours = async () => {
      if (
        formik.values.establishmentTransportSchedules &&
        formik.values.establishmentTransportSchedules.length > 0
      ) {
        const hoursMap = new Map(establishmentHours);

        const currentIds = new Set<number>();

        for (const schedule of formik.values.establishmentTransportSchedules) {
          const id = Number(schedule.idEstablishment);
          if (!id) continue;

          currentIds.add(id);

          if (hoursMap.has(id)) {
            continue;
          }

          try {
            const establishmentHoursById = await getEstablishmentHoursById(id.toString());
            hoursMap.set(id, {
              establishmentName: schedule.establishmentName,
              hours: establishmentHoursById || [],
            });
          } catch (error: any) {
            enqueueSnackbar(error.message, { variant: 'error' });
          }
        }

        for (const existingId of Array.from(hoursMap.keys())) {
          if (!currentIds.has(existingId)) {
            hoursMap.delete(existingId);
          }
        }

        setEstablishmentHours(hoursMap);
      } else {
        setEstablishmentHours(new Map());
      }
    };

    fetchEstablishmentHours();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [formik.values.establishmentTransportSchedules, getEstablishmentHoursById]);

  const handleEstablishmentHoursUpdate = () => {
    if (selectedEstablishment) {
      const { establishmentHoursById: currentHours } = useEstablishmentStore.getState();
      if (currentHours && currentHours.length > 0) {
        setEstablishmentHours((prevMap) => {
          const newMap = new Map(prevMap);
          newMap.set(selectedEstablishment.id, {
            establishmentName: selectedEstablishment.name,
            hours: currentHours,
          });
          return newMap;
        });
      }
    }
  };

  const isDataReady = isSchedulesLoaded;

  const memoizedFormFields = useMemo(() => {
    const fields = getPassengerFormFields(
      establishmentOptions,
      departmentOptions,
      searchEstablishments
    );
    const handleScheduleChange = (newSchedules: EstablishmentSchedule[]) => {
      setFrontendSchedules(newSchedules);
      formik.setFieldValue(
        'establishmentTransportSchedules',
        componentToApiStructure(newSchedules)
      );
    };
    const getEstablishmentError = (index: number): string | undefined => {
      const errors =
        formik.errors?.establishmentTransportSchedules &&
        formik.touched?.establishmentTransportSchedules;
      if (errors) {
        if (typeof formik.errors.establishmentTransportSchedules === 'string') {
          return formik.errors.establishmentTransportSchedules;
        }

        if (Array.isArray(formik.errors.establishmentTransportSchedules)) {
          const error = formik.errors.establishmentTransportSchedules[index];
          if (error && typeof error !== 'string' && error.idEstablishment) {
            return error.idEstablishment;
          }
        }
      }
      return undefined;
    };
    const handleFieldBlur = (index: number) => {
      formik.handleBlur(`establishmentTransportSchedules[${index}].idEstablishment`);
    };

    return (
      <>
        <Grid item xs={12}>
          <AvatarUploader onUpload={() => void 0} isReadOnly={isReadOnly || loading} />
        </Grid>
        {fields.map((field) => {
          if (field.name === 'establishmentTransportSchedules') {
            if (!isDataReady) {
              return (
                <Grid item xs={12} key="etablissements-jours-loading">
                  <StyledCircularProgress size={15} color="inherit" />
                </Grid>
              );
            }

            return (
              <>
                <React.Fragment key="etablissements-jours">
                  <EtablissementJoursField
                    mode={mode}
                    setSharedSchedules={
                      setSharedSchedules as Dispatch<SetStateAction<WeekSchedule[]>>
                    }
                    field={{
                      ...field,
                      name: 'establissements',
                      label: 'Établissement',
                    }}
                    values={{ establishmentTransportSchedules: frontendSchedules }}
                    errors={getEstablishmentError}
                    isReadOnly={(mode === 'edit' && isUsagerAttachedToAmendment) || isReadOnly}
                    etablissementsOptions={establishmentOptions}
                    onFieldChange={(name, value) => {
                      if (name === 'establishmentTransportSchedules') handleScheduleChange(value);
                    }}
                    handleFieldBlur={handleFieldBlur}
                    onAddEstablishment={handleAddEstablishment}
                  />
                </React.Fragment>
              </>
            );
          }

          return (
            <Grid sx={centerFlexColumn} item xs={12} sm={4} key={field.name}>
              {renderField(field, { onAddInfrastructure: handleAddInfrastructure })}
            </Grid>
          );
        })}
      </>
    );
  }, [
    establishmentOptions,
    departmentOptions,
    searchEstablishments,
    isReadOnly,
    loading,
    formik,
    renderField,
    isDataReady,
    frontendSchedules,
    mode,
  ]);

  return (
    <>
      <ConditionalComponent isValid={isReadOnly}>
        <EditExportButtons
          onEdit={() => onEdit(usager)}
          onExport={() => void 0}
          tooltipTitle={TableType.Usager}
          dataRow={usager}
          tableHead={tableHead}
        />
      </ConditionalComponent>
      <Grid container spacing={4} sx={{ pt: 2 }}>
        {memoizedFormFields}
      </Grid>
      <ConditionalComponent isValid={formik.values.establishmentTransportSchedules.length > 0}>
        <ConditionalComponent
          isValid={!establishmentHoursLoading}
          defaultComponent={
            <Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center', pt: 2 }}>
              <StyledCircularProgress size={35} color="primary" />
            </Box>
          }
        >
          <Grid container spacing={2} sx={{ mt: 2 }}>
            {Array.from(establishmentHours.entries()).map(([idEstablishment, data]) => (
              <Grid item xs={12} key={`establishment-schedule-${idEstablishment}`}>
                <ScheduleTable
                  title={`${data.establishmentName} (Horaire)`}
                  mode="time"
                  isInEstablishment
                  scheduleData={data.hours}
                  secoundaryColor
                  actionButton={
                    <EditExportButtons
                      onEdit={() => {
                        setSelectedEstablishment({
                          id: idEstablishment,
                          name: data.establishmentName,
                          hours: data.hours,
                        });
                        setModalOpen(true);
                      }}
                      tooltipTitle={"Horaire de l'établissement"}
                    />
                  }
                />
              </Grid>
            ))}
          </Grid>
        </ConditionalComponent>
      </ConditionalComponent>
      <ConditionalComponent isValid={!isReadOnly}>
        <Grid item xs={12} sx={{ mt: 2 }}>
          <ActionButtons onSave={handleSave} onCancel={onClose} mode={mode} loading={loading} />
        </Grid>
      </ConditionalComponent>

      {selectedEstablishment && (
        <UpdateEstablishmentHoursModal
          open={modalOpen}
          onClose={() => {
            setModalOpen(false);
            setSelectedEstablishment(null);
          }}
          establishmentId={selectedEstablishment.id}
          establishmentName={selectedEstablishment.name}
          initialHours={selectedEstablishment.hours}
          onHoursUpdated={handleEstablishmentHoursUpdate}
        />
      )}

      <CreateEtablissementModal
        open={openEstablishmentModal}
        onClose={handleCloseEstablishmentModal}
        PaperProps={{
          style: {
            height: '90vh',
            width: '80%',
            maxWidth: 'none',
          },
        }}
      />
      <CreateInfrastructureModal
        open={openInfrastructureModal}
        onClose={handleCloseInfrastructureModal}
        PaperProps={{
          style: {
            height: '90vh',
            width: '80%',
            maxWidth: 'none',
          },
        }}
      />
    </>
  );
}
