"use client"

import React, { useEffect, useRef, useCallback } from "react"
import { Grid, IconButton, InputAdornment, Autocomplete, Alert, CircularProgress, Box } from "@mui/material"
import { centerFlexColumn, StyledTextField } from "@/shared/theme/css"
import FormField from "@/shared/components/form/form-field"
import { TableColumn, TableType, type FormFieldType, type ModeType } from "@/shared/types/common"
import type { IDriverAbsence } from "@/shared/types/driver-absence"
import FormContainer from "@/layouts/form/form-container"
import ActionButtons from "@/shared/components/form/buttons-action"
import EditExportButtons from "@/shared/components/form/edit-export-buttons"
import { formFieldsDriverAbsence } from "../utils/form-fields-absence"
import { useResponsive } from "@/hooks"
import { faPaperclip } from "@fortawesome/free-solid-svg-icons"
import FontAwesome from "@/shared/components/fontawesome"
import CustomTooltip from "@/shared/components/tooltips/tooltip-custom"
import { useFormik } from "formik"
import { driverAbsenceValidationSchema } from "../utils/driver-absence-validation"
import ConditionalComponent from "@/shared/components/table/ConditionalComponent"
import { useDriverStore } from "@/shared/api/stores/driverStore"
import { useCollaboratorStore } from "@/shared/api/stores/CollaboratorStore"
import { IDriverType } from "@/shared/types/driver"

import { useDriverAbsenceStore } from "@/shared/api/stores/driverAbsenceStore"
import { BinaryQuestion } from "@/shared/types/trajet"
import { useDocumentStore } from "@/shared/api/stores/document-service/documentStore"
import { useTripDriverAssignmentStore } from "@/shared/api/stores/circuit-service/tripDriverAssignmentStore"
import { enqueueSnackbar } from 'notistack'

const searchDrivers = (name: string) => {
  useDriverStore.getState().fetchDrivers({ firstName: name, lastName: name });
};

interface AbsenceFormProps {
  absence: IDriverAbsence;
  mode: ModeType;
  onSave: (updatedAbsence: IDriverAbsence) => void | Promise<void>;
  onEdit: (updatedAbsence: IDriverAbsence) => void;
  onClose: (forceClose: boolean) => void;
  isTraiteAbsence?: boolean;
  tableHead: TableColumn[];
  updateTabContent?: (tabId: string, content: IDriverAbsence) => void;
  tabId?: string;
}

export default function AbsenceDriverForm({
  absence,
  mode,
  onSave,
  onClose,
  onEdit,
  isTraiteAbsence,
  tableHead,
  updateTabContent,
  tabId
}: AbsenceFormProps) {
  const isBetweenSmAndLg = useResponsive("between", "sm", "lg");
  const fileInputRef = useRef<HTMLInputElement>(null);
  const isReadOnly = mode === "view";
  const drivers = useDriverStore((state) => state.drivers) || [];
  const autocompleteDrivers = useDriverStore((state) => state.autocompleteDrivers);
  const [autoOptions, setAutoOptions] = React.useState<Array<{ id: number; firstName: string; lastName: string }>>([]);
  const [inputValue, setInputValue] = React.useState("");
  const typingTimeoutRef = useRef<NodeJS.Timeout | null>(null);
  const lastQueryRef = useRef<string>("");
  const [selectedChauffeurOption, setSelectedChauffeurOption] = React.useState<{ id: number; firstName: string; lastName: string } | null>(null);
  const hasLoadedInitialOptionsRef = useRef<boolean>(false);

  const autocompleteCollaborator = useCollaboratorStore((state) => state.autocompleteCollaborator);
  const [collabOptions, setCollabOptions] = React.useState<Array<{ id: number; firstName: string; lastName: string }>>([]);
  const [authorizedInputValue, setAuthorizedInputValue] = React.useState("");
  const authorizedTypingTimeoutRef = useRef<NodeJS.Timeout | null>(null);
  const authorizedLastQueryRef = useRef<string>("");
  const [selectedAuthorizedOption, setSelectedAuthorizedOption] = React.useState<{ id: number; firstName: string; lastName: string } | null>(null);

  // Helper to get collaborator name by ID
  const getCollaboratorNameById = React.useCallback((id: string | number | null | undefined): string => {
    if (!id) return '';
    
    // Convert to number if string
    const numId = typeof id === 'string' ? parseInt(id) : id;
    
    // Try to find in collabOptions
    const collab = collabOptions.find(c => c.id === numId);
    if (collab) {
      return `${collab.firstName} ${collab.lastName}`;
    }
    
    // Return empty string if not found
    return '';
  }, [collabOptions]);

  // Fetch collaborator name if missing from backend response
  const fetchCollaboratorNameIfMissing = React.useCallback(async (id: string | number | null | undefined) => {
    if (!id) return '';
    
    try {
      const numId = typeof id === 'string' ? parseInt(id) : id;
      const collaborator = await useCollaboratorStore.getState().getCollaboratorById(numId);
      if (collaborator) {
        return `${collaborator.firstName} ${collaborator.lastName}`;
      }
    } catch (error) {
      console.error('Failed to fetch collaborator:', error);
    }
    return '';
  }, []);

  // État pour gérer l'affectation du chauffeur
  const [isDriverAssigned, setIsDriverAssigned] = React.useState<boolean | null>(null);
  const [checkingAssignment, setCheckingAssignment] = React.useState<boolean>(false);
  const { checkDriverAssignment } = useTripDriverAssignmentStore();
  const lastCheckRef = useRef<string>(''); // Pour éviter les appels multiples

  const formik = useFormik<IDriverAbsence>({
    initialValues: absence,
    validationSchema: driverAbsenceValidationSchema,
    onSubmit: (values) => {
      if (mode === "add") {
        handleCreate(values);
      } else {
        handleUpdate(values);
      }
    },
  });

  const getDriverById = useCallback((id: string | null | undefined): IDriverType | null => {
    if (!id) return null;
    return drivers.find((driver) => parseInt(driver.id) === parseInt(id)) || null;
  }, [drivers]);

  const [authorizedBy, setAuthorizedBy] = React.useState<IDriverType | null>(() => getDriverById(absence.autorisePar));
  const [validatedBy, setValidatedBy] = React.useState<IDriverType | null>(() => getDriverById(absence.validePar));

  useEffect(() => {
    formik.setFieldValue('autorisePar', absence.autorisePar ? absence.autorisePar : null);
    formik.setFieldValue('validePar', absence.validePar ? absence.validePar : null);
  }, []);

  // Set initial values for autorisePar and validePar from absence data
  useEffect(() => {
    if (mode === 'view' || mode === 'edit') {
      // For autorisePar, try to get from authorizedByName first, then autorisePar
      if (absence.authorizedByName) {
        formik.setFieldValue('autorisePar', absence.authorizedByName);
      } else if (absence.autorisePar) {
        formik.setFieldValue('autorisePar', absence.autorisePar);
      }
      
      // For validePar, try to get from validatedByName first, then validePar
      if (absence.validatedByName) {
        formik.setFieldValue('validePar', absence.validatedByName);
      } else if (absence.validePar) {
        formik.setFieldValue('validePar', absence.validePar);
      }
    }
  }, [absence, mode, formik.setFieldValue]);

  // Set validatedBy state for Autocomplete in edit mode
  useEffect(() => {
    if (mode === 'edit' && absence.validePar) {
      // Find the driver who validated the absence
      const validator = drivers.find(driver => driver.id === absence.validePar);
      if (validator) {
        setValidatedBy(validator);
      }
    }
  }, [mode, absence.validePar, drivers]);

  useEffect(() => {
    if (mode === "add" && !hasLoadedInitialOptionsRef.current) {
      hasLoadedInitialOptionsRef.current = true;
      autocompleteDrivers().then((list) => setAutoOptions(list ?? []));
      autocompleteCollaborator().then((list) => setCollabOptions(list ?? []));
    }
  }, [mode, autocompleteDrivers, autocompleteCollaborator]);

  // ✅ WORKAROUND: Fetch collaborator names if missing from backend
  useEffect(() => {
    const fetchMissingNames = async () => {
      if ((mode === 'view' || mode === 'edit') && absence) {
        // Fetch authorized by name if we have ID but no name
        if (absence.autorisePar && !absence.authorizedByName) {
          const name = await fetchCollaboratorNameIfMissing(absence.autorisePar);
          if (name) {
            formik.setFieldValue('autorisePar', name);
          }
        }
        
        // Fetch validated by name if we have ID but no name
        if (absence.validePar && !absence.validatedByName) {
          const name = await fetchCollaboratorNameIfMissing(absence.validePar);
          if (name) {
            formik.setFieldValue('validePar', name);
          }
        }
      }
    };
    
    fetchMissingNames();
  }, [mode, absence, absence?.autorisePar, absence?.validePar, absence?.authorizedByName, absence?.validatedByName, fetchCollaboratorNameIfMissing]);

  useEffect(() => {
    return () => {
      if (typingTimeoutRef.current) clearTimeout(typingTimeoutRef.current);
      if (authorizedTypingTimeoutRef.current) clearTimeout(authorizedTypingTimeoutRef.current);
    };
  }, []);
  const checkDriverAssignmentStatus = useCallback(async (driverId: string, startDate: string, endDate: string) => {
    if (!driverId || !startDate || !endDate) {
      setIsDriverAssigned(null);
      return;
    }

    // Éviter les appels multiples si déjà en cours
    if (checkingAssignment) {
      return;
    }

    setCheckingAssignment(true);
    try {
      const isAssigned = await checkDriverAssignment(parseInt(driverId), startDate, endDate);
      setIsDriverAssigned(isAssigned);
      // Auto-check the radio based on assignment status
      formik.setFieldValue('chauffeurAffecte', isAssigned ? BinaryQuestion.Oui : BinaryQuestion.Non);
    } catch (error) {
      console.error('Erreur lors de la vérification de l\'affectation:', error);
      setIsDriverAssigned(null);
    } finally {
      setCheckingAssignment(false);
    }
  }, [checkDriverAssignment, formik.setFieldValue, checkingAssignment]);

  useEffect(() => {
    const { chauffeur, dateDebut, dateFin } = formik.values;
    // In edit/view mode, use absence.driver.id, in add mode use chauffeur
    const driverId = mode === "add" ? chauffeur : (absence.driver?.id ? String(absence.driver.id) : null);
    
    if (driverId && dateDebut && dateFin) {
      // Créer une clé unique pour éviter les appels multiples
      const checkKey = `${driverId}-${dateDebut}-${dateFin}`;
      
      // Vérifier si on a déjà fait cette vérification
      if (lastCheckRef.current === checkKey) {
        return;
      }
      
      // Mettre à jour la référence et faire la vérification
      lastCheckRef.current = checkKey;
      checkDriverAssignmentStatus(driverId, dateDebut, dateFin);
    } else {
      setIsDriverAssigned(null);
      lastCheckRef.current = '';
    }
  }, [formik.values.chauffeur, formik.values.dateDebut, formik.values.dateFin, checkDriverAssignmentStatus, mode, absence.driver?.id]);

  const handleUserSelect = (fieldName: string, driver: IDriverType | null) => {
    if (fieldName === 'autorisePar') {
      setAuthorizedBy(driver);
    } else if (fieldName === 'validePar') {
      setValidatedBy(driver);
    } else if (fieldName === 'chauffeur') {
      formik.setFieldValue(fieldName, driver ? String(driver.id) : null);
    }
  };

  // Fonction pour vérifier l'affectation du chauffeur

  const handleIconClick = () => {
    if (fileInputRef.current) {
      fileInputRef.current.click();
    }
  };

  const handleFileUpload = (event: React.ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0];
    if (file) {
      formik.setFieldValue('justificatif', file);
    }
  };

  const renderField = (field: FormFieldType<IDriverAbsence>) => {
    if (field.name === "justificatif") {
      const error = formik.touched[field.name] && formik.errors[field.name];
      return (
        <StyledTextField
          isSmallScreen={isBetweenSmAndLg}
          fullWidth
          name={field.name}
          InputLabelProps={{ shrink: true }}
          value={formik.values[field.name] ? formik.values[field.name].name : ""}
          onBlur={formik.handleBlur}
          error={!!error}
          helperText={error ? String(formik.errors[field.name]) : undefined}
          label={field.label}
          placeholder={field.placeholder}
          sx={{
            ...(isReadOnly && {
              '& .MuiInputBase-root': {
                backgroundColor: '#f5f5f5',
                cursor: 'not-allowed',
              },
              '& .MuiInputBase-input': {
                cursor: 'not-allowed',
                color: 'text.disabled',
              }
            })
          }}
          InputProps={{
            readOnly: isReadOnly,
            endAdornment: (
              <InputAdornment position="end">
                <CustomTooltip title="Importer la justification" arrow>
                  <IconButton onClick={handleIconClick} disabled={isReadOnly}>
                    <FontAwesome
                      icon={faPaperclip}
                      sx={{
                        color: isReadOnly ? 'text.disabled' : "primary.main",
                        width: isBetweenSmAndLg ? 16 : 18,
                      }}
                    />
                  </IconButton>
                </CustomTooltip>
              </InputAdornment>
            )
          }}
        />
      );
    }

    return (
      <FormField
        field={field}
        value={formik.values[field.name]}
        onChange={(name, value) => {
          if (field.type === "date") {
            formik.setFieldValue(name, value.split('T')[0])
          }else{
            formik.setFieldValue(name, value)
          }
        }}
        error={
          formik.touched[field.name]
            ? (formik.errors[field.name] as string | undefined)
            : undefined
        }
        onBlur={formik.handleBlur}
        isReadOnly={field.name === "chauffeurAffecte" ? true : isReadOnly}
      />
    );
  };

  const handleCreate = async (values: IDriverAbsence) => {
    try {
      // const document = await useDocumentStore.getState().upload(values.justificatif, values.chauffeur);
  
      const createdAbsence = await useDriverAbsenceStore.getState().createAbsence({
        ...values,
        supportingDocumentId: 0,
        driverId: parseInt(values.chauffeur),
        absenceType: values.typeAbsence,
        startDate: new Date(values.dateDebut),
        endDate: new Date(values.dateFin),
        nbHours: parseInt(values.nombreHeures),
        receptionMode: values.modeReception,
        driverTraject: values.chauffeurAffecte === BinaryQuestion.Oui,
        isAssigned: values.chauffeurAffecte === BinaryQuestion.Oui,
        validatedBy: values.validePar ? parseInt(values.validePar) : null,
        authorizedBy: values.autorisePar ? parseInt(values.autorisePar) : null,
        status: values.statut
      });
      
      enqueueSnackbar("Absence créée avec succès", { variant: 'success' });
      onSave(values);
      onClose(true);
    } catch (error: any) {
      // Check for duplicate absence error and replace the message
      const message = error?.response?.data?.message || error?.message || "Erreur lors de la création de l'absence";
  
      // Check for the duplicate message
      if (message.includes("Duplicate absence found for the same period")) {
        enqueueSnackbar("L'absence ne peut pas être dupliquée pour le même chauffeur et même date", { variant: 'error' });
      } else {
        enqueueSnackbar(message, { variant: 'error' });
      }
    }
  };
  
  const handleUpdate = async (values: IDriverAbsence) => {
    try {
      // let document = absence.supportingDocumentId ?? 0;
      // if (values.justificatif !== absence.justificatif) {
      //   document = await useDocumentStore.getState().upload(values.justificatif, values.chauffeur);
      // }
  
      const updatedAbsence = await useDriverAbsenceStore.getState().updateAbsence(absence.id, {
        ...values,
        supportingDocumentId: 0,
        driverId: absence.driver?.id ? parseInt(absence.driver.id) : parseInt(values.chauffeur),
        driverName: absence.driverName ? values.driverName : `${absence.driver?.firstName} ${absence.driver?.lastName}`,
        absenceType: values.typeAbsence,
        startDate: new Date(values.dateDebut),
        endDate: new Date(values.dateFin),
        nbHours: parseInt(values.nombreHeures),
        receptionMode: values.modeReception,
        driverTraject: values.chauffeurAffecte === BinaryQuestion.Oui,
        isAssigned: values.chauffeurAffecte === BinaryQuestion.Oui,
        validatedBy: values.validePar ? parseInt(values.validePar) : null,
        authorizedBy: values.autorisePar ? parseInt(values.autorisePar) : null,
        status: values.statut,
      });
      
      enqueueSnackbar("Absence mise à jour avec succès", { variant: 'success' });
      if (updateTabContent && tabId) {
        updateTabContent(tabId, values);
      } else {
        onEdit(values);
      }
      onClose(true);
    } catch (error: any) {
      const message = error?.response?.data?.message || error?.message || "Erreur lors de la mise à jour de l'absence";
  
      // Check for the duplicate message
      if (message.includes("Duplicate absence found for the same period")) {
        enqueueSnackbar("L'absence ne peut pas être dupliquée pour le même chauffeur et même date", { variant: 'error' });
      } else {
        enqueueSnackbar(message, { variant: 'error' });
      }
    }
  };
  

  return (
    <FormContainer titre="Fiche d'absence chauffeur">
      <ConditionalComponent isValid={isReadOnly}>
        <EditExportButtons
          onEdit={isTraiteAbsence ? undefined : () => onEdit(absence)}
          onExport={() => void 0}
          tooltipTitle={TableType.absence}
          dataRow={absence}
          tableHead={tableHead}
        />
      </ConditionalComponent>

      <form onSubmit={formik.handleSubmit}>
        <Grid container spacing={4}>
          {formFieldsDriverAbsence.filter((field) =>
            !(field.name === "validePar" && (mode === "edit" || mode === "add"))
          ).map((field) => (
            <Grid item xs={12} sm={4} sx={centerFlexColumn} key={field.name}>
              {field.name === "chauffeur" ? (
                <Autocomplete
                  options={mode === "add" ? autoOptions : drivers}
                  getOptionLabel={(option: any) => `${option.firstName} ${option.lastName}`}
                  onInputChange={(event, newInputValue, reason) => {
                    setInputValue(newInputValue);
                    if (mode === "add") {
                      if (reason !== 'input') return; // avoid calls on mount/select/clear
                      if (newInputValue === lastQueryRef.current) return;
                      lastQueryRef.current = newInputValue;
                      if (typingTimeoutRef.current) clearTimeout(typingTimeoutRef.current);
                      typingTimeoutRef.current = setTimeout(() => {
                        const q = (lastQueryRef.current || '').trim();
                        if (q.length === 0) return; // no fetch on empty input
                        if (q.length < 2) {
                          // skip very short queries
                          return;
                        }
                        autocompleteDrivers(q).then((list) => setAutoOptions(list ?? []));
                      }, 700);
                    } else {
                      if (reason !== 'input') return;
                      if (newInputValue === lastQueryRef.current) return;
                      lastQueryRef.current = newInputValue;
                      if (typingTimeoutRef.current) clearTimeout(typingTimeoutRef.current);
                      typingTimeoutRef.current = setTimeout(() => {
                        const q = (lastQueryRef.current || '').trim();
                        if (q.length < 3) return;
                        searchDrivers(q);
                      }, 700);
                    }
                  }}
                  onBlur={() => {
                    const q = (lastQueryRef.current || '').trim();
                    if (q.length >= 2) {
                      if (mode === 'add') {
                        autocompleteDrivers(q).then((list) => setAutoOptions(list ?? []));
                      } else {
                        searchDrivers(q);
                      }
                    }
                  }}
                  onChange={(event, value: any) => {
                    if (mode === "add") {
                      setSelectedChauffeurOption(value ?? null);
                      formik.setFieldValue(field.name, value ? String(value.id) : null);
                    } else {
                      handleUserSelect(field.name, value);
                    }
                  }}
                  isOptionEqualToValue={(option: any, value: any) => !!option && !!value && option.id === value.id}
                  disableClearable={mode === "view"}
                  disabled={mode === "view" || mode === "edit"}
                  value={
                    mode === "add"
                      ? selectedChauffeurOption
                      : (absence.driver ?? null)
                  }
                  renderInput={(params) => (
                    (() => {
                      const hasErr = mode === "view" || mode === "edit" ? false : !!(formik.touched[field.name] && formik.errors[field.name]);
                      const msg = hasErr ? String(formik.errors[field.name]) : undefined;
                      return (
                        <StyledTextField
                          {...params}
                          label={field.label}
                          disabled={mode === "view" || mode === "edit"}
                          onBlur={formik.handleBlur}
                          error={hasErr}
                          helperText={msg}
                          sx={{ '& .MuiInputBase-root': { height: 55 } }}
                        />
                      );
                    })()
                  )}
                />
              ) : field.name === "autorisePar" ? (
                (mode === "view" || mode === "edit") ? (
                  <StyledTextField
                    fullWidth
                    label={field.label}
                    value={
                      absence.authorizedByName || 
                      getCollaboratorNameById(formik.values[field.name]) || 
                      formik.values[field.name] || 
                      ''
                    }
                    InputProps={{
                      readOnly: true,
                      sx: {
                        '& .MuiInputBase-root': {
                          backgroundColor: '#f5f5f5',
                          cursor: 'not-allowed',
                        },
                        '& .MuiInputBase-input': {
                          cursor: 'not-allowed',
                          color: 'text.disabled',
                        }
                      }
                    }}
                  />
                ) : (
                  <Autocomplete
                    options={collabOptions}
                    getOptionLabel={(option: any) => `${option.firstName} ${option.lastName}`}
                    onInputChange={(event, newInputValue, reason) => {
                      setAuthorizedInputValue(newInputValue);
                      if (reason !== 'input') return; // avoid calls on mount/select/clear
                      if (newInputValue === authorizedLastQueryRef.current) return;
                      authorizedLastQueryRef.current = newInputValue;
                      if (authorizedTypingTimeoutRef.current) clearTimeout(authorizedTypingTimeoutRef.current);
                      authorizedTypingTimeoutRef.current = setTimeout(() => {
                        const q = (authorizedLastQueryRef.current || '').trim();
                        if (q.length === 0) return; // no fetch on empty input
                        if (q.length < 2) return;
                        autocompleteCollaborator(q).then((list) => setCollabOptions(list ?? []));
                      }, 700);
                    }}
                    onBlur={() => {
                      const q = (authorizedLastQueryRef.current || '').trim();
                      if (q.length >= 2) {
                        autocompleteCollaborator(q).then((list) => setCollabOptions(list ?? []));
                      }
                    }}
                    onChange={(event, value: any) => {
                      setSelectedAuthorizedOption(value ?? null);
                      formik.setFieldValue('autorisePar', value ? String(value.id) : null);
                    }}
                    isOptionEqualToValue={(option: any, value: any) => !!option && !!value && option.id === value.id}
                    value={selectedAuthorizedOption}
                    renderInput={(params) => (
                      (() => {
                        const hasErr = !!(formik.touched[field.name] && formik.errors[field.name]);
                        const msg = hasErr ? String(formik.errors[field.name]) : undefined;
                        return (
                          <StyledTextField
                            {...params}
                            label={field.label}
                            onBlur={formik.handleBlur}
                            error={hasErr}
                            helperText={msg}
                            sx={{ '& .MuiInputBase-root': { height: 55 } }}
                          />
                        );
                      })()
                    )}
                  />
                )
                              ) : field.name === "validePar" ? (
                  // Show validePar only for processed absences in view mode
                  mode === "view" && isTraiteAbsence === false ? (
                    <StyledTextField
                      fullWidth
                      label={field.label}
                      value={
                        absence.validatedByName || 
                        getCollaboratorNameById(formik.values[field.name]) || 
                        formik.values[field.name] || 
                        ''
                      }
                      InputProps={{
                        readOnly: true,
                        sx: {
                          '& .MuiInputBase-root': {
                            backgroundColor: '#f5f5f5',
                            cursor: 'not-allowed',
                          },
                          '& .MuiInputBase-input': {
                            cursor: 'not-allowed',
                            color: 'text.disabled',
                          }
                        }
                      }}
                    />
                  ) : null
              ) : (
                renderField(field)
              )}
            </Grid>
          ))}
          <input type="file" ref={fileInputRef} style={{ display: "none" }} onChange={handleFileUpload} />
          
          <Grid item xs={12}>
            <ConditionalComponent isValid={mode !== "view"}>
              <ActionButtons
                onSave={() => {
                  formik.validateForm().then(() => {
                    formik.submitForm();
                  });
                }}
                onCancel={() => onClose(false)}
                mode={mode}
              />
            </ConditionalComponent>
          </Grid>
        </Grid>
      </form>
    </FormContainer>
  );
}