"use client"

import React, { useEffect, useState, useCallback, useRef, useMemo } from "react"
import { Box, FormHelperText, Grid, Typography } from "@mui/material"
import { LotList, mapLotToLotRequest, type DepartmentRequest, type LotRequest } from "@/shared/types/infrastructure"
import FormField from "@/shared/components/form/form-field"
import type { FormFieldType, ModeType, TableColumn } from "@/shared/types/common"
import FormContainer from "@/layouts/form/form-container"
import { mainLotFormFields } from "../utils/lot-form-fields"
import { FormikTouched, useFormik } from "formik"
import EditExportButtons from "@/shared/components/form/edit-export-buttons"
import ConditionalComponent from "@/shared/components/table/ConditionalComponent"
import { useSnackbar } from "notistack"
import { useInfrastructureStore } from "@/shared/api/stores/admin-service/infrastructureStore"
import ActionButtons from "@/shared/components/form/buttons-action"
import { lotSchema } from "../utils/lot-validation"

interface LotFormProps {
  lot: LotList
  mode: ModeType
  onEdit: (lot: LotList) => void
  onClose: (forceClose: boolean) => void
  tableHead?: TableColumn[]
  updateTabContent?: (tabId: string, content: any) => void
  tabId?: string
  markTabAsSaved?: (tabId: string, content: any) => void
  tabContent?: LotList
}

export default function LotForm({
  lot,
  mode,
  onEdit,
  onClose,
  tableHead = [],
  updateTabContent,
  tabId,
  markTabAsSaved,
  tabContent
}: LotFormProps) {
  const isReadOnly = mode === "view"

  const { enqueueSnackbar } = useSnackbar();

  const [lotFormData, setLotFormData] = useState<LotRequest>({} as LotRequest);
  const [departmentOptions, setDepartmentOptions] = useState<{ value: string, label: string }[]>([]);
  const [numberAvailability, setNumberAvailability] = useState<{ message: string, isAvailable: boolean } | null>(null);
  const previousFormDataRef = useRef<LotRequest | null>(null);

  const {
    error,
    clearError,
    departmentNames,
    fetchDepartmentNames,
    getLotById,
    createLot,
    updateLot,
    existsLotByNumberLoading,
    existsLotByNumber,
  } = useInfrastructureStore();

  useEffect(() => {
    fetchDepartmentNames();
  }, []);

  const getInitialValues = async () => {
    if (lot.id && mode !== 'add') {
      const lotData = await getLotById(lot.id);
      if (lotData) {
        setLotFormData(mapLotToLotRequest(lotData));
      }
    }
  }

  useEffect(() => {
    // Use tab content if available, otherwise fetch from API
    if (tabContent && typeof tabContent === 'object') {
      // tabContent is the formik.values (LotRequest) from updateTabContent
      // Check if it has departmentsIds property to determine if it's Request or List
      const hasDepartmentsIds = 'departmentsIds' in tabContent;
      
      if (hasDepartmentsIds) {
        // It's already a LotRequest from formik.values
        setLotFormData(tabContent as LotRequest);
      } else {
        // Convert LotList to LotRequest format (needs API call for departmentsIds)
        const mappedData: LotRequest = {
          id: tabContent.id,
          number: tabContent.number,
          description: tabContent.description,
          departmentsIds: []
        };
        setLotFormData(mappedData);
        // Load departmentsIds from API
        if (tabContent.id) {
          getLotById(tabContent.id).then((lotData) => {
            if (lotData) {
              const fullData = mapLotToLotRequest(lotData);
              setLotFormData(fullData);
            }
          });
        }
      }
      previousFormDataRef.current = null; // Reset the ref
    } else if (mode === 'add' || (lot.id && Object.keys(lotFormData).length === 0)) {
      getInitialValues();
      previousFormDataRef.current = null; // Reset the ref
    }
  }, [lot.id, mode, tabContent]);

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

  const handleFormSubmit = async (values: LotRequest) => {
    if (numberAvailability != null && !numberAvailability.isAvailable) {
      enqueueSnackbar('Veuillez entrer un numéro valide !', { variant: 'error' });
      return;
    }
    if (mode === 'add' || mode === 'copy') {
      try {
        await createLot(values);
        enqueueSnackbar('Lot créé avec succès', { variant: 'success' });
        // Pour le mode création, on retourne à la liste car on ne peut pas rester sans ID
        onClose(true);
      } catch (error: any) {
        enqueueSnackbar(error.message, { variant: 'error' });
        clearError();
        return;
      }
    } else if (mode === 'edit') {
      if (!lot?.id) {
        enqueueSnackbar('Erreur: ID du lot manquant', { variant: 'error' });
        return;
      }
      try {
        await updateLot(lot.id, values);
        enqueueSnackbar('Lot modifié avec succès', { variant: 'success' });
        // Rester dans le formulaire en mode "view" au lieu de retourner à la liste
        if (markTabAsSaved) {
          // Recharger les données complètes pour avoir le bon format
          const fullLotData = await getLotById(lot.id);
          if (fullLotData) {
            markTabAsSaved(tabId!, fullLotData);
          } else {
            onClose(true);
          }
        } else {
          onClose(true);
        }
      } catch (error: any) {
        enqueueSnackbar(error.message, { variant: 'error' });
        clearError();
        return;
      }
    }
  };

  // Use tab content directly if available, otherwise use form data
  const initialValues = useMemo(() => {
    if (tabContent && typeof tabContent === 'object') {
      // Check if it's already a LotRequest
      if ('departmentsIds' in tabContent) {
        return tabContent as LotRequest;
      }
      // Otherwise it's LotList, use lotFormData which will have departmentsIds from API
    }
    return lotFormData;
  }, [tabContent, lotFormData]);

  const formik = useFormik<LotRequest>({
    initialValues: initialValues,
    validationSchema: lotSchema,
    onSubmit: handleFormSubmit,
    enableReinitialize: true,
  })

  useEffect(() => {
    if (mode === 'add') {
      setLotFormData({} as LotRequest);
      formik.resetForm();
    }
  }, [mode]);

  useEffect(() => {
    if (updateTabContent && tabId && mode !== "view") {
      const timer = setTimeout(() => {
        updateTabContent(tabId, formik.values)
      }, 300)

      return () => {
        clearTimeout(timer)
      }
    }
  }, [formik.values, updateTabContent, tabId, mode])

  const numberTimeoutRef = useRef<NodeJS.Timeout>();

  const checkNumber = useCallback((number: string) => {
    if (numberTimeoutRef.current) {
      clearTimeout(numberTimeoutRef.current);
    }

    if (!number) {
      setNumberAvailability(null);
      return;
    }

    const trimmedNumber = number.trim();
    if (trimmedNumber === '') {
      setNumberAvailability(null);
      return;
    }

    numberTimeoutRef.current = setTimeout(() => {
      const verifyNumber = async () => {
        try {
          const exists = mode === 'edit'
            ? await existsLotByNumber(trimmedNumber, Number(lot.id))
            : await existsLotByNumber(trimmedNumber);

          setNumberAvailability({
            message: exists ? 'Le numéro existe déjà' : 'Le numéro est disponible',
            isAvailable: !exists
          });
        } catch (error) {
          setNumberAvailability(null);
        }
      };

      verifyNumber();
    }, 500);
  }, [mode, lot.id, existsLotByNumber]);

  useEffect(() => {
    return () => {
      if (numberTimeoutRef.current) {
        clearTimeout(numberTimeoutRef.current);
      }
    };
  }, []);

  const renderField = (field: FormFieldType<LotRequest>) => {
    const fieldValue = formik.values[field.name as keyof LotRequest]
    const value = field.type === "multiple"
      ? (Array.isArray(fieldValue) ? fieldValue.filter(v => v !== null) : [])
      : fieldValue

    return (
      <>
        <FormField
          field={field}
          value={value}
          onChange={(name, value) => {
            formik.setFieldValue(name, value);
            if (field.name === 'number') {
              checkNumber(value);
            }
          }}
          error={
            formik.touched[field.name as keyof LotRequest]
              ? (formik.errors[field.name as keyof LotRequest] as string | undefined)
              : undefined
          }
          onBlur={formik.handleBlur}
          isReadOnly={field.name === 'departmentsIds' ? (mode === 'view' || mode === 'edit') : isReadOnly}
        />
        <ConditionalComponent isValid={field.name === 'number'}>
          <FormHelperText
            sx={{
              color: existsLotByNumberLoading ? 'text.secondary' : (numberAvailability?.isAvailable ? 'success.main' : 'error.main'),
              marginTop: '4px',
              display: 'flex',
              alignItems: 'center'
            }}
          >
            <ConditionalComponent isValid={existsLotByNumberLoading}>
              <Box sx={{ display: 'flex', alignItems: 'center' }}>
                <Box
                  sx={{
                    width: '16px',
                    height: '16px',
                    border: '2px solid #f3f3f3',
                    borderTop: '2px solid #746CD4',
                    borderRadius: '50%',
                    animation: 'spin 1s linear infinite',
                    marginRight: '8px',
                    '@keyframes spin': {
                      '0%': { transform: 'rotate(0deg)' },
                      '100%': { transform: 'rotate(360deg)' }
                    }
                  }}
                />
                <Typography sx={{ color: '#746CD4' }}>
                  Vérification en cours...
                </Typography>
              </Box>
            </ConditionalComponent>
            <ConditionalComponent isValid={!existsLotByNumberLoading}>
              {numberAvailability?.message}
            </ConditionalComponent>
          </FormHelperText>
        </ConditionalComponent>
      </>
    )
  }

  useEffect(() => {
    if (error) {
      enqueueSnackbar(error, { variant: 'error' })
      clearError()
    }
  }, [error, enqueueSnackbar, clearError])

  return (
    <FormContainer sx={{ width: "100%" }}>
      <ConditionalComponent isValid={isReadOnly}>
        <EditExportButtons
          onEdit={() => onEdit(lot)}
          tooltipTitle="Lot"
          dataRow={formik.values}
          tableHead={tableHead}
        />
      </ConditionalComponent>

      <form onSubmit={formik.handleSubmit}>
        <Box
          sx={{
            width: "100%",
            display: "flex",
            flexDirection: "column",
            alignItems: "center",
            justifyContent: "center",
          }}
        >
          <Grid
            container
            spacing={2}
            direction="column"
            alignItems="center"
            justifyContent="center"
            sx={{ minHeight: "100%", maxWidth: "600px", margin: "auto" }}
          >
            {mainLotFormFields(departmentOptions).map((field) => (
              <Grid item xs={12} key={field.name} sx={{ width: "100%" }}>
                {renderField(field)}
              </Grid>
            ))}

            <ConditionalComponent isValid={!isReadOnly}>
              <Grid container spacing={2} justifyContent="flex-end" sx={{ mt: 3 }}>
                <ActionButtons
                  onSave={() => {
                    formik.validateForm().then((errors) => {
                      const hasErrors = Object.keys(errors).length > 0;
                      if (!hasErrors) {
                        formik.submitForm();
                      } else {
                        formik.setTouched(
                          Object.keys(errors).reduce((acc, key) => {
                            acc[key as keyof DepartmentRequest] = true;
                            return acc;
                          }, {} as FormikTouched<DepartmentRequest>)
                        );
                      }
                    });
                  }}
                  onCancel={() => onClose(false)}
                  mode={mode} />
              </Grid>
            </ConditionalComponent>
          </Grid>
        </Box>
      </form>
    </FormContainer>
  )
}
