"use client"

import { useEffect } from "react"
import { Grid, Typography } from "@mui/material"
import { useFormik } from "formik"
import FormField from "@/shared/components/form/form-field"
import { TableType, type FormFieldType, type ModeType, type TableColumn, type AddressData } from "@/shared/types/common"
import FormContainer from "@/layouts/form/form-container"
import ActionButtons from "@/shared/components/form/buttons-action"
import { preparationUsagerFormFields } from "../utils/form-fields-passenger"
import EditExportButtons from "@/shared/components/form/edit-export-buttons"
import { type FieldType, useMultipleFields } from "@/hooks/use-multiple-fields"
import DuplicableField from "@/shared/components/form/duplicable-field"
import type { IPreparationUsager } from "@/shared/types/usager"
import { createEmptyJoursAttribues, etablissementsOptions } from "@/shared/_mock/_avenantUsager"
import type { JoursAttribues } from "@/shared/types/chauffeur"
import JoursAttribuesInput from "@/shared/components/form/jours-attribues-input"
import { getLabel } from "@/shared/_mock"
import React from "react"
import { preparationUsagerSchema } from "../utils/preparation-usager-schema"

interface PreparationUsagerFormProps {
  preparationUsager: IPreparationUsager
  mode: ModeType
  onSave: (updated: IPreparationUsager) => void
  onEdit: (updated: IPreparationUsager) => void
  onClose: (forceClose: boolean) => void
  tableHead: TableColumn[]
  updateTabContent?: (tabId: string, newContent: IPreparationUsager) => void
  tabId?: string
}

export default function PreparationUsagerForm({
  preparationUsager,
  mode,
  onSave,
  onClose,
  onEdit,
  tableHead,
  updateTabContent,
  tabId,
}: PreparationUsagerFormProps) {
  const isReadOnly = mode === "view"

  const formik = useFormik<IPreparationUsager>({
    initialValues: {
      ...preparationUsager,
      etablissement: preparationUsager.etablissement?.length ? preparationUsager.etablissement : [""],
      adressEtb: preparationUsager.adressEtb?.length
  ? preparationUsager.adressEtb
  : [{
      address: "",
      lat: 0,
      lng: 0,
      city: "",
      postalCode: "",
      country: ""
    }],
      jours: preparationUsager.jours?.length ? preparationUsager.jours : [createEmptyJoursAttribues()],
    },
    validationSchema: preparationUsagerSchema,
    onSubmit: (values) => {
      onSave(values)
      onClose(true)
    },
  })

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

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


  const { fields, handleAdd, handleDelete, handleChange } = useMultipleFields({
    initialValues: {
      etablissement: formik.values.etablissement?.length ? formik.values.etablissement : [""],
    },
    onChange: (type, newValues) => {
      formik.setFieldValue(type, newValues)
    },
    isReadOnly,
  })

  useEffect(() => {
    if (
      fields.etablissement?.length !== formik.values.jours?.length ||
      fields.etablissement?.length !== formik.values.adressEtb?.length
    ) {
      const newJoursData: JoursAttribues[] = []
      const newAddressData: AddressData[] = []

      for (let i = 0; i < Math.min(formik.values.jours?.length || 0, fields.etablissement?.length || 0); i++) {
        newJoursData[i] = JSON.parse(JSON.stringify(formik.values.jours?.[i] || createEmptyJoursAttribues()))
      }

      for (let i = 0; i < Math.min(formik.values.adressEtb?.length || 0, fields.etablissement?.length || 0); i++) {
        newAddressData[i] = {
          ...(formik.values.adressEtb?.[i] || {}),
          address: formik.values.adressEtb?.[i]?.address || "",
          lat: formik.values.adressEtb?.[i]?.lat ?? 0,
          lng: formik.values.adressEtb?.[i]?.lng ?? 0,
          city: formik.values.adressEtb?.[i]?.city || "",
          postalCode: formik.values.adressEtb?.[i]?.postalCode || "",
          country: formik.values.adressEtb?.[i]?.country || "",
          placeId: formik.values.adressEtb?.[i]?.placeId,
          formattedAddress: formik.values.adressEtb?.[i]?.formattedAddress,
        };
      }

      while (newJoursData.length < (fields.etablissement?.length || 0)) {
        newJoursData.push(createEmptyJoursAttribues())
      }

      while (newAddressData.length < (fields.etablissement?.length || 0)) {
        newAddressData.push({
          address: "",
          lat: 0,
          lng: 0,
          city: "",
          postalCode: "",
          country: "",
        });
      }

      formik.setFieldValue("jours", newJoursData)
      formik.setFieldValue("adressEtb", newAddressData)
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [fields.etablissement?.length, formik.values.jours, formik.values.adressEtb])

  const handleAddEtablissement = () => {
    handleAdd("etablissement")
  }

  const handleDeleteEtablissement = (type: FieldType, index: number) => {
    handleDelete("etablissement", index)
    const newJoursData = formik.values.jours?.filter((_, i) => i !== index) || []
    const newAddressData = formik.values.adressEtb?.filter((_, i) => i !== index) || []
    formik.setFieldValue("jours", newJoursData)
    formik.setFieldValue("adressEtb", newAddressData)
  }

  const renderEtablFields = (field: FormFieldType<IPreparationUsager>) => {
    const etablissementFields = fields.etablissement?.length ? fields.etablissement : [""]

    return etablissementFields.map((value, index) => (
      <React.Fragment key={`etablissement-${index}`}>
        <DuplicableField
          formData={formik.values}
          fieldType={"etablissement"}
          field={field}
          index={index}
          value={value}
          isReadOnly={isReadOnly}
          onChange={handleChange}
          onAdd={handleAddEtablissement}
          onDelete={handleDeleteEtablissement}
          sx={{ mt: 3 }}
          error={
            Boolean((formik.touched.etablissement as any)?.[index]) && (formik.errors.etablissement as any)?.[index]
              ? String((formik.errors.etablissement as any)[index])
              : undefined
          }
          onBlur={formik.handleBlur}
        />

        <Grid item xs={12} sm={4} sx={{ mt: 3 }}>
          <FormField
            field={{
              name: `adressEtb.${index}.address` as keyof IPreparationUsager,
              label: `Adresse (${getLabel(value, etablissementsOptions) || `Établissement ${index + 1}`})`,
              type: "address",
            }}
            value={formik.values.adressEtb?.[index]?.address || ""}
            onChange={(_, value) => {
              const newAddresses = [...(formik.values.adressEtb || [])]
              while (newAddresses.length <= index) {
                newAddresses.push({
                  address: "",
                  lat: 0,
                  lng: 0,
                  city: "",
                  postalCode: "",
                  country: "",
                });
              }
              newAddresses[index] = value
              formik.setFieldValue("adressEtb", newAddresses)
            }}
            error={
              Boolean((formik.touched.adressEtb as any)?.[index]?.address) &&
              (formik.errors.adressEtb as any)?.[index]?.address
                ? String((formik.errors.adressEtb as any)[index].address)
                : undefined
            }
            onBlur={formik.handleBlur}
            isReadOnly={isReadOnly}
          />
        </Grid>

        <Grid item xs="auto">
          <Typography sx={{ color: (theme) => theme.palette.primary.main }}>
            {`Jours (${getLabel(value, etablissementsOptions) || `Établissement ${index + 1}`})`}
          </Typography>
          <JoursAttribuesInput
            initialJours={formik.values.jours?.[index] || createEmptyJoursAttribues()}
            otherJours={formik.values.jours?.filter((_, idx) => idx !== index)}
            onChange={(updatedJours) => {
              const newJoursData = [...(formik.values.jours || [])]
              while (newJoursData.length <= index) {
                newJoursData.push(createEmptyJoursAttribues())
              }
              newJoursData[index] = updatedJours
              formik.setFieldValue("jours", newJoursData)
            }}
            isReadOnly={isReadOnly}
          />
        </Grid>
      </React.Fragment>
    ))
  }

  const renderField = (field: FormFieldType<IPreparationUsager>) => (
    <FormField
      field={field}
      value={formik.values[field.name as keyof IPreparationUsager]}
      onChange={(name, value) => formik.setFieldValue(name, value)}
      error={
        formik.touched[field.name as keyof IPreparationUsager] && formik.errors[field.name as keyof IPreparationUsager]
          ? field.name === "adresse"
            ? (formik.errors.adresse as any)?.address
            : String(formik.errors[field.name])
          : undefined
      }
      onBlur={formik.handleBlur}
      isReadOnly={isReadOnly}
    />
  )

  return (
    <FormContainer titre="Fiche Préparation Usagers">
      
      {isReadOnly ? (
        <EditExportButtons
          onEdit={() => onEdit(formik.values)}
          onExport={() => void 0}
          tooltipTitle={TableType.Usager}
          dataRow={preparationUsager}
          tableHead={tableHead}
        />
      ) : null}
      <form onSubmit={formik.handleSubmit}>
        <Grid container spacing={4}>
          {preparationUsagerFormFields.map((field) =>
            field.name === "etablissement" ? (
              renderEtablFields(field)
            ) : (
              <Grid item xs={12} sm={4} sx={field.name === "observation" ? { mt: 3 } : undefined} key={field.name}>
                {renderField(field)}
              </Grid>
            ),
          )}
          <Grid item xs={12}>
            {!isReadOnly ? <ActionButtons onSave={formik.submitForm} onCancel={() => onClose(false)} mode={mode} /> : null}
          </Grid>
        </Grid>
      </form>


    </FormContainer>
  )
}
