'use client';

import { useCallback, useMemo, useState, useEffect } from 'react';
import { useFormikContext, getIn } from 'formik';
import { debounce } from '@mui/material';
import { enqueueSnackbar } from 'notistack';
import type { Representative, IPassengerList } from '@/shared/types/passenger';
import type { AmendmentPassengerDetails } from '@/shared/types/ammendment-passenger';
import type { Address } from '@/shared/types/establishment';
import { AddressType } from '@/shared/types/establishment';
import { useCircuitStore } from '@/shared/api/stores/circuit-service/circuitStore';
import type { CircuitWithSpecificInfoResponse } from '@/shared/api/stores/circuit-service/circuitStore';
import type { SelectedDaysType } from '@/shared/types/usager';
import { UseRepresentantFormProps, variantConfig } from '../../../../types/representant-form.types';
import {
  convertSchedulesToSelectedDays,
  convertSelectedDaysToSchedules,
} from '../../../../utils/schedule-converters';

export function useRepresentantForm({
  data,
  variant,
  tabIndex,
  onChange,
  mode,
}: UseRepresentantFormProps) {
  const [circuitOptions, setCircuitOptions] = useState<{ value: string; label: string }[]>([]);
  const isReadOnly = mode === 'view';
  const isAddMode = mode === 'add';
  const formik = useFormikContext<IPassengerList | AmendmentPassengerDetails>();
  const config = variantConfig[variant];
  const formikPath = config.formikPath;
  const { searchWithSpecificInfoByCircuitCode } = useCircuitStore();

  const mapCircuitsToOptions = useCallback((circuits: CircuitWithSpecificInfoResponse[]) => {
    return circuits.map((circuit) => ({
      value: circuit.id,
      label: circuit.circuitCode,
    }));
  }, []);

  useEffect(() => {
    const loadInitialCircuits = async () => {
      try {
        const circuits = await searchWithSpecificInfoByCircuitCode();
        const options = mapCircuitsToOptions(circuits);
        setCircuitOptions(options);
      } catch (error) {
        enqueueSnackbar('Erreur lors du chargement des circuits', { variant: 'error' });
      }
    };

    loadInitialCircuits();
  }, [searchWithSpecificInfoByCircuitCode, mapCircuitsToOptions]);

  const selectedDays = useMemo(
    () => convertSchedulesToSelectedDays(data.transportSchedulesRepresentative),
    [data.transportSchedulesRepresentative]
  );

  useEffect(() => {
    const transportSchedules = (formik.values as any)[formikPath][tabIndex]
      ?.transportSchedulesRepresentative;
    if (!transportSchedules || transportSchedules.length === 0) {
      const defaultSelectedDays = convertSchedulesToSelectedDays([]);
      updateSelectedDays(defaultSelectedDays);
    }
  }, [(formik.values as any)[formikPath][tabIndex]?.transportSchedulesRepresentative]);

  const getCircuitsRaw = useCallback(
    async (query?: string) => {
      try {
        let circuits: CircuitWithSpecificInfoResponse[];
        if (!query || query.trim() === '') {
          circuits = await searchWithSpecificInfoByCircuitCode(undefined, undefined);
        } else {
          const trimmedQuery = query.trim();
          const isId =data.circuitId === trimmedQuery;
          
          if (isId) {
            circuits = await searchWithSpecificInfoByCircuitCode(undefined, trimmedQuery);
          } else {
            circuits = await searchWithSpecificInfoByCircuitCode(trimmedQuery, undefined);
          }
        }        const options = mapCircuitsToOptions(circuits);
        setCircuitOptions(options);
      } catch (error) {
        enqueueSnackbar('Erreur lors de la recherche des circuits', { variant: 'error' });
      }
    },
    [searchWithSpecificInfoByCircuitCode, data.circuitId, mapCircuitsToOptions],
  );

  const getCircuits = useMemo(() => debounce(getCircuitsRaw, 300), [getCircuitsRaw]);

  const getAddressByType = useCallback(
    (type: AddressType) => {
      return data.addresses.find((addr) => addr.addressType === type) || ({} as Address);
    },
    [data.addresses]
  );

  const formData = useMemo(
    () => ({
      ...data,
      additionalAddress: getAddressByType(AddressType.REPRESENTATIVE)?.additionalAddress || '',
      pickupAddress: getAddressByType(AddressType.PICKUP)?.additionalAddress || '',
      circuitId: data.circuitId || '',
      mobile:
        data.contacts[0]?.mobilePhoneNumbers?.length > 0
          ? data.contacts[0].mobilePhoneNumbers
          : [''],
      fixe:
        data.contacts[0]?.landlinePhoneNumbers?.length > 0
          ? data.contacts[0].landlinePhoneNumbers
          : [''],
      personne:
        data.contacts[0]?.assignedPersonNames?.length > 0
          ? data.contacts[0]?.assignedPersonNames
          : [''],
      notificationArivee: data.arrivalNotification,
      autorisationParentale: data.parentalAuthorization,
    }),
    [data, getAddressByType]
  );

  const updateSelectedDays = useCallback(
    (newSchedule: SelectedDaysType) => {
      const updatedData: Partial<Representative> = {
        ...data,
        transportSchedulesRepresentative: convertSelectedDaysToSchedules(newSchedule),
      };
      onChange(updatedData);
    },
    [data, onChange]
  );

  const getFieldError = useCallback(
    (fieldName: string) => {
      let fieldPath: string;
      if (fieldName === 'addresses') {
        const addressIndex =
          (formik.values as any)[formikPath]?.[tabIndex]?.addresses?.findIndex(
            (addr: Address) => addr.addressType === AddressType.REPRESENTATIVE
          ) ?? -1;
        fieldPath = `${formikPath}[${tabIndex}].addresses${addressIndex >= 0 ? `[${addressIndex}].additionalAddress` : ''}`;
      } else {
        fieldPath = `${formikPath}[${tabIndex}].${fieldName}`;
      }
      const touched = getIn(formik.touched, fieldPath);
      const error = getIn(formik.errors, fieldPath);
      return touched && error ? String(error) : undefined;
    },
    [formik.touched, formik.errors, formik.values, tabIndex, formikPath]
  );

  const shouldDisableField = useCallback(
    (fieldName: string, isEditMode: boolean, disabledFields: string[]) => {
      if (fieldName === 'circuitId' && isAddMode && variant === 'standard') {
        return true;
      }

      if (!isEditMode) return false;

      if (!disabledFields.includes(fieldName)) return false;
      switch (fieldName) {
        case 'firstName':
          return data.firstName !== '' && data.firstName !== null && data.firstName !== undefined;
        case 'lastName':
          return data.lastName !== '' && data.lastName !== null && data.lastName !== undefined;
        case 'addresses':
          return (
            data.addresses &&
            data.addresses.length > 0 &&
            data.addresses.some(
              (addr) => addr.additionalAddress !== '' && addr.additionalAddress !== null
            )
          );
        case 'circuitId':
          return data.circuitId !== '' && data.circuitId !== null && data.circuitId !== undefined;
        default:
          return false;
      }
    },
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [isReadOnly]
  );

  const shouldDisableSchedules = useCallback(
    (isEditMode: boolean) => {
      if (!isEditMode) return false;
      return data.transportSchedulesRepresentative.some((schedule: any) => {
        return (
          schedule.dayScheduleRepresentative &&
          Array.isArray(schedule.dayScheduleRepresentative) &&
          schedule.dayScheduleRepresentative.length > 0
        );
      });
    },
    [isReadOnly] // Pas de dépendances car on utilise useRef
  );

  return {
    circuitOptions,
    selectedDays,
    formikPath,
    formData,
    getCircuits,
    getAddressByType,
    updateSelectedDays,
    getFieldError,
    shouldDisableField,
    shouldDisableSchedules,
    formik,
  };
}
