"use client"

import { useState, useEffect } from "react"
import { Typography, Grid, Box } from "@mui/material"
import FormField from "@/shared/components/form/form-field"
import type { FormFieldType, ModeType } from "@/shared/types/common"
import JoursAttribuesInput from "@/shared/components/form/jours-attribues-input"
import type { IAvenantUsager, IUsager } from "@/shared/types/usager"
import { usagerAvenantFormFields1, usagerAvenantFormFields2 } from "../../../utils/form-fields-avenant"
import TabbedForm from "@/shared/components/tabs/tabbed-form"
import HorairesSpecifiqueTabs from "./horaires-specifique-tabs"
import ActionButtons from "@/shared/components/form/buttons-action"
import EditExportButtons from "@/shared/components/form/edit-export-buttons"
import RepresentantTabs from "../representant/representant-tabs"
import { type FieldType, useMultipleFields } from "@/hooks/use-multiple-fields"
import DuplicableField from "@/shared/components/form/duplicable-field"
import type { JoursAttribues } from "@/shared/types/chauffeur"
import { createEmptyJoursAttribues, etablissementsOptions } from "@/shared/_mock/_avenantUsager"
import { getLabel } from "@/shared/_mock"
import { useFormik } from "formik"
import { avenantUsagerSchema } from "../../../utils/usager-validation"
import ConditionalComponent from "@/shared/components/table/ConditionalComponent"
import { IPassengerList } from "@/shared/types/passenger"

interface AvenantUsagersFormProps {
  avenant: IAvenantUsager
  mode: ModeType
  onSave: (updatedusager: IAvenantUsager) => void
  onEdit: (updatedusager: IAvenantUsager) => void
  onClose: () => void
  usager: IPassengerList
}

const prependNomPrenom = (objetAvenant: string | undefined, nom: string, prenom: string) => {
  const nomPrenom = `${nom} ${prenom}: `
  return objetAvenant?.startsWith(nomPrenom) ? objetAvenant : nomPrenom + (objetAvenant || "")
}

export default function AvenantsHorairesForm({
  avenant,
  mode,
  onSave,
  onClose,
  onEdit,
  usager,
}: AvenantUsagersFormProps) {
  const isReadOnly = mode === "view"

  const initialJours = avenant.jours?.length
    ? avenant.jours
    : avenant.etablissement?.map(() => createEmptyJoursAttribues()) || [createEmptyJoursAttribues()]

  const [joursData, setJoursData] = useState<JoursAttribues[]>(initialJours)

  const formik = useFormik<IAvenantUsager>({
    initialValues: avenant,
    validationSchema: avenantUsagerSchema,
    onSubmit: (values) => {
      const updatedFormData = {
        ...values,
        objetAvenant: prependNomPrenom(values.objetAvenant, usager.firstName, usager.lastName),
        etablissement: fields.etablissement,
        jours: joursData,
      }
      onSave(updatedFormData)
      onClose()
    },
  })

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

  useEffect(() => {
    if (fields.etablissement?.length !== joursData.length) {
      const newJoursData: JoursAttribues[] = []
      for (let i = 0; i < Math.min(joursData.length, fields.etablissement?.length || 0); i++) {
        newJoursData[i] = JSON.parse(JSON.stringify(joursData[i]))
      }
      while (newJoursData.length < (fields.etablissement?.length || 0)) {
        newJoursData.push(createEmptyJoursAttribues())
      }

      setJoursData(newJoursData)
      formik.setFieldValue('jours', newJoursData)
    }
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [fields.etablissement?.length, joursData])

  useEffect(() => {
    formik.setFieldValue(
      'objetAvenant',
      prependNomPrenom(formik.values.objetAvenant, usager.firstName, usager.lastName)
    )
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [usager.firstName, usager.lastName])

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

  const handleDeleteEtablissement = (type: FieldType, index: number) => {
    handleDelete("etablissement", index)
    const newJoursData = joursData.filter((_, i) => i !== index)
    setJoursData(newJoursData)
    formik.setFieldValue('jours', newJoursData)
  }

  const renderField = (field: FormFieldType<IAvenantUsager>) => {
    const error = formik.touched[field.name] && formik.errors[field.name]
    return (
      <FormField
        field={field}
        value={formik.values[field.name]}
        onChange={(name, value) => formik.setFieldValue(name, value)}
        error={error ? String(formik.errors[field.name]) : undefined}
        isReadOnly={isReadOnly}
        onBlur={formik.handleBlur}
      />
    )
  }

  const renderEtablAndJoursFields = (field: FormFieldType<IAvenantUsager>) => {
    return fields.etablissement?.map((value, index) => (
      <>
        <DuplicableField
          formData={formik.values}
          key={`etablissement-${index}`}
          fieldType={"etablissement"}
          field={field}
          index={index}
          value={value}
          isReadOnly={isReadOnly}
          onChange={handleChange}
          onAdd={handleAddEtablissement}
          onDelete={handleDeleteEtablissement}
          sx={{ mt: 3 }}
        />
        <Grid item xs={12} md={8} xl={4} key={`jours-${index}`}>
          <Typography sx={{ color: (theme) => theme.palette.primary.main }}>
            {`Jours (${getLabel(value, etablissementsOptions) || `Établissement ${index + 1}`})`}
          </Typography>
          <JoursAttribuesInput
            initialJours={joursData[index]}
            otherJours={joursData.filter((_, idx) => idx !== index)}
            onChange={(updatedJours) => {
              const newJoursData = joursData.map((jour, idx) => (idx === index ? updatedJours : { ...jour }))
              setJoursData(newJoursData)
              formik.setFieldValue('jours', newJoursData)
            }}
            isReadOnly={isReadOnly}
          />
        </Grid>
        <Grid item xs={0} xl={4}></Grid>
      </>
    ))
  }

  const handleSave = () => {
    formik.validateForm().then((errors) => {
      formik.submitForm()
    })
  }

  const tabs = [
    {
      label: "Représentant, Adresses et Circuits",
      content: <RepresentantTabs scheduleMode={mode} />,
    },
    {
      label: "Horaires spécifiques",
      content: (
        <HorairesSpecifiqueTabs
          title="Horaires spécifiques de usager"
          isReadOnly={isReadOnly}
          withData={mode !== "add"}
        />
      ),
    },
  ]

  return (
    <Box
      sx={{
        pt: 3,
        px: 2,
        pb: 1,
        borderRadius: "0px 16px 16px 16px",
        border: (theme) => `2px solid ${theme.palette.primary.main}`,
      }}
    >
      <Typography
        variant="h5"
        sx={{
          color: "primary.main",
          fontWeight: (theme) => theme.typography.fontWeightBold,
          pb: 2,
        }}
      >
        Avenant usager
      </Typography>
      <ConditionalComponent isValid={isReadOnly}>
        <EditExportButtons onEdit={() => onEdit(avenant)} onExport={() => void 0} tooltipTitle="l'avenant" />
      </ConditionalComponent>
      <form onSubmit={formik.handleSubmit}>
        <Grid container spacing={4}>
          {usagerAvenantFormFields1.map((field) =>
            <ConditionalComponent key={field.name} defaultComponent={renderEtablAndJoursFields(field)} isValid={field.name !== "etablissement"}>
              <Grid item xs={12} sm={4} key={field.name}>
                {renderField(field)}
              </Grid>
            </ConditionalComponent>
          )}
          {usagerAvenantFormFields2.map((field) => (
            <Grid item xs={12} sm={4} key={field.name}>
              {renderField(field)}
            </Grid>
          ))}
        </Grid>

        <TabbedForm tabs={tabs} sx={{ mt: 4, mb: 1 }} hasBorder />

        <ConditionalComponent isValid={!isReadOnly}>
          <Grid item xs={12}>
            <ActionButtons onSave={handleSave} onCancel={onClose} mode={mode} />
          </Grid>
        </ConditionalComponent>
      </form>
    </Box>
  )
}
