"use client"

import React, { useCallback, useEffect, useRef, useState } from "react"
import { Box, FormHelperText, Grid, Typography } from "@mui/material"
import { FormikTouched, useFormik } from "formik"
import FormField from "@/shared/components/form/form-field"
import type { FormFieldType, ModeType } from "@/shared/types/common"
import EditExportButtons from "@/shared/components/form/edit-export-buttons"
import ActionButtons from "@/shared/components/form/buttons-action"
import FormContainer from "@/layouts/form/form-container"
import ConditionalComponent from "@/shared/components/table/ConditionalComponent"
import { mapVehicleBrandModelToRequest, VehicleBrandModel } from "@/shared/types/fleet-management/vehicle-brand-model"
import { vehicleModelSchema } from "../utils/vehicle-brand-model-schema"
import { useVehicleBrandModelStore } from "@/shared/api/stores/fleet-service/vehicle-brand-model-store"
import { useSnackbar } from "notistack"
import { vehicleBrandModelFormFields } from "../utils/form-fields-vehicle-brand-model"
import { useVehicleTypeStore } from "@/shared/api/stores/fleet-service/vehicle-type-store"
import { VehicleBrandModelRequest } from "@/shared/types/fleet-management/vehicle-brand-model"

interface VehicleBrandModelFormProps {
  vehicleBrandModel: VehicleBrandModel
  mode: ModeType
  onEdit: (updatedVehicleModel: VehicleBrandModelRequest) => void
  onClose: (isSaved: boolean) => void;
  setHasUnsavedChanges?: (value: boolean) => void
  updateTabContent?: (tabId: string, newContent: VehicleBrandModelRequest) => void
  tabId?: string
}

export default function VehicleBrandModelForm({
  vehicleBrandModel,
  mode,
  onClose,
  onEdit,
  setHasUnsavedChanges,
  updateTabContent,
  tabId
}: VehicleBrandModelFormProps) {

  const { enqueueSnackbar } = useSnackbar();

  const isReadOnly = mode === "view"

  const [formData, setFormData] = useState<VehicleBrandModelRequest>({} as VehicleBrandModelRequest);

  const [vehicleTypeOptions, setVehicleTypeOptions] = useState<{ value: string; label: string }[]>([]);

  const [brandAndModelNamesAvailability, setBrandAndModelNamesAvailability] = useState<{ message: string; isAvailable: boolean } | null>(null);

  const {
    vehicleBrandModelById,
    getVehicleBrandModelById,
    createVehicleBrandModel,
    updateVehicleBrandModel,
    existsByBrandNameAndModelNameLoading,
    existsByBrandNameAndModelName,
  } = useVehicleBrandModelStore();

  const {
    allVehicleTypes,
    fetchAllVehicleTypes
  } = useVehicleTypeStore();

  const handleFormSubmit = async (values: VehicleBrandModelRequest) => {
    if (brandAndModelNamesAvailability != null && !brandAndModelNamesAvailability.isAvailable) {
      enqueueSnackbar('Veuillez entrer une marque et un modèle valide !', { variant: 'error' });
      return;
    }
    if (mode === 'edit') {
      try {
        await updateVehicleBrandModel(vehicleBrandModel.id, values);
        if (setHasUnsavedChanges) setHasUnsavedChanges(false);
        onClose(true);
        enqueueSnackbar('Marque modèle modifié avec succès', { variant: 'success' });
      } catch (error: any) {
        enqueueSnackbar(error.message, { variant: 'error' });
        return;
      }
    } else if (mode === 'add' || mode === 'copy') {
      try {
        await createVehicleBrandModel(values);
        if (setHasUnsavedChanges) setHasUnsavedChanges(false);
        onClose(true);
        enqueueSnackbar('Marque modèle créé avec succès', { variant: 'success' });
      } catch (error: any) {
        enqueueSnackbar(error.message, { variant: 'error' });
        return;
      }
    }
  };

  const formik = useFormik<VehicleBrandModelRequest>({
    initialValues: formData,
    validationSchema: vehicleModelSchema,
    enableReinitialize: true,
    onSubmit: handleFormSubmit
  })

  const getInitialValues = async () => {
    if (vehicleBrandModel.id && mode !== 'add') {
      await getVehicleBrandModelById(vehicleBrandModel.id);
    }
  }

  useEffect(() => {
    fetchAllVehicleTypes();
    getInitialValues();
  }, []);

  useEffect(() => {
    if (allVehicleTypes) {
      setVehicleTypeOptions(allVehicleTypes.map((vehicleType) => ({ value: vehicleType.id, label: vehicleType.name })));
    }
  }, [allVehicleTypes])

  useEffect(() => {
    if (mode !== 'add' && vehicleBrandModelById) {
      setFormData(mapVehicleBrandModelToRequest(vehicleBrandModelById));
    }
  }, [vehicleBrandModelById]);

  useEffect(() => {
    if (mode === 'add') {
      setFormData({} as VehicleBrandModelRequest)
    }
  }, [mode, vehicleBrandModel])

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

  const checkBrandModelNames = useCallback((brandName: string, modelName: string) => {
    if (brandModelNamesTimeoutRef.current) {
      clearTimeout(brandModelNamesTimeoutRef.current);
    }

    if (!brandName || !modelName) {
      setBrandAndModelNamesAvailability(null);
      return;
    }

    const trimmedBrandName = brandName.trim();
    const trimmedModelName = modelName.trim();
    if (trimmedBrandName === '' || trimmedModelName === '') {
      setBrandAndModelNamesAvailability(null);
      return;
    }

    brandModelNamesTimeoutRef.current = setTimeout(() => {
      const verifyBrandModelNames = async () => {
        try {
          const existsResult = mode === 'edit'
            ? await existsByBrandNameAndModelName(trimmedBrandName, trimmedModelName, vehicleBrandModel.id)
            : await existsByBrandNameAndModelName(trimmedBrandName, trimmedModelName);

          setBrandAndModelNamesAvailability({
            message: existsResult ? 'La marque avec le modèle existent déjà' : 'La marque avec le modèle sont disponible',
            isAvailable: !existsResult
          });
        } catch (error) {
          setBrandAndModelNamesAvailability(null);
        }
      };

      verifyBrandModelNames();
    }, 500);
  }, [mode, vehicleBrandModel.id, existsByBrandNameAndModelName]);

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

  useEffect(() => {
    if (updateTabContent && tabId && (mode !== "view")) {
      updateTabContent(tabId, formik.values)
    }
  }, [formik.values, updateTabContent, tabId, mode])

  const renderField = (field: FormFieldType<VehicleBrandModelRequest>) => {
    const handleChange = (name: string, value: any) => {
      formik.setFieldValue(name, value);

      if (name === 'brandName') {
        checkBrandModelNames(value, formik.values.modelName);
      }

      if (name === 'modelName') {
        checkBrandModelNames(formik.values.brandName, value);
      }
    };

    return (
      <>
        <FormField
          field={field}
          value={formik.values[field.name as keyof VehicleBrandModelRequest]}
          onChange={handleChange}
          error={
            formik.touched[field.name as keyof VehicleBrandModelRequest]
              ? (formik.errors[field.name as keyof VehicleBrandModelRequest] as string | undefined)
              : undefined
          }
          onBlur={formik.handleBlur}
          isReadOnly={field.disabled || isReadOnly}
        />
        <ConditionalComponent isValid={field.name === 'brandName' || field.name === 'modelName'}>
          <FormHelperText
            sx={{
              color: existsByBrandNameAndModelNameLoading ? 'text.secondary' : (brandAndModelNamesAvailability?.isAvailable ? 'success.main' : 'error.main'),
              marginTop: '4px',
              display: 'flex',
              alignItems: 'center'
            }}
          >
            <ConditionalComponent isValid={existsByBrandNameAndModelNameLoading}>
              <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={!existsByBrandNameAndModelNameLoading}>
              {brandAndModelNamesAvailability?.message}
            </ConditionalComponent>
          </FormHelperText>
        </ConditionalComponent>
      </>
    )
  }

  return (
    <FormContainer titre="Marque / Modèle">
      <ConditionalComponent isValid={isReadOnly}>
        <EditExportButtons onEdit={() => onEdit(formik.values)} tooltipTitle="le modèle" />
      </ConditionalComponent>

      <form onSubmit={formik.handleSubmit}>
        <Grid container spacing={5}>
          {vehicleBrandModelFormFields(vehicleTypeOptions).map((field) => (
            <Grid item xs={12} sm={4} key={field.name}>
              {renderField(field)}
            </Grid>
          ))}

          <ConditionalComponent isValid={!isReadOnly}>
            <Grid item xs={12}>
              <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 VehicleBrandModelRequest] = true;
                          return acc;
                        }, {} as FormikTouched<VehicleBrandModelRequest>)
                      );
                    }
                  });
                }}
                onCancel={() => {
                  onClose(false);
                }}
                mode={mode}
              />
            </Grid>
          </ConditionalComponent>
        </Grid>
      </form>
    </FormContainer>
  )
}