"use client"

import type React from "react"
import { useCallback, useEffect, useMemo, useState } from "react"
import { Grid, Button, IconButton } from "@mui/material"
import type { FormFieldType, ModeType } from "@/shared/types/common"
import FormField from "@/shared/components/form/form-field"
import ScheduleTable from "@/shared/components/form/schedule-table"
import FontAwesome from "@/shared/components/fontawesome"
import { faAnglesDown, faAnglesUp, faSquareMinus } from "@fortawesome/free-solid-svg-icons"
import {
  contactFormFields,
  contactsFormFields,
  disabledFields,
  mainRepresentantformFields,
} from "../../../utils/form-fields-representative"
import { Box } from "@mui/system"
import { centerFlexColumn, iconButtonStyles } from "@/shared/theme/css"
import { pxToRem } from "@/shared/theme/typography"
import { useMultipleFields } from "@/hooks/use-multiple-fields"
import DuplicableField from "@/shared/components/form/duplicable-field"
import { useFormikContext, getIn } from "formik"
import type { Representative, IPassengerList } from "@/shared/types/passenger"
import { convertSchedulesToSelectedDays, convertSelectedDaysToSchedules } from "../../../utils/schedule-converters"
import { type Address, AddressType } from "@/shared/types/establishment"
import type { SelectedDaysType } from "@/shared/types/usager"
import ConditionalComponent from "@/shared/components/table/ConditionalComponent"
import CustomTooltip from "@/shared/components/tooltips/tooltip-custom"
import type { AmendmentPassengerDetails } from "@/shared/types/ammendment-passenger"
import type { CircuitAutocompleteResponse } from "@/shared/api/stores/circuit-service/circuitStore"
import { useCircuitStore } from "@/shared/api/stores/circuit-service/circuitStore"
import { enqueueSnackbar } from "notistack"

interface BaseRepresentantFormProps {
  data: Representative
  isReadOnly: boolean
  withContact?: boolean
  onChange: (newData: Partial<Representative>) => void
  tabIndex: number
  mode: ModeType
}

interface StandardFormProps extends BaseRepresentantFormProps {
  variant: "standard"
  handleTabClose?: never
}

interface AmendmentFormProps extends BaseRepresentantFormProps {
  variant: "amendment"
  handleTabClose: (event: React.MouseEvent, tabId: number) => void
}

type RepresentantFormProps = StandardFormProps | AmendmentFormProps

const typeMap = {
  mobilePhoneNumbers: "mobile",
  landlinePhoneNumbers: "fixe",
  assignedPersonNames: "personne",
} as const

const variantConfig = {
  standard: {
    formikPath: "representatives",
    contextType: "IPassengerList" as const,
  },
  amendment: {
    formikPath: "amendmentRepresentatives",
    contextType: "AmendmentPassengerDetails" as const,
  },
} as const

export default function UnifiedRepresentantForm(props: RepresentantFormProps) {
  const { data, mode, isReadOnly, onChange, withContact, tabIndex, variant } = props

  const handleTabClose = variant === "amendment" ? props.handleTabClose : undefined

  const [circuitCode] = useState(data.circuitCode)
  const isEditMode = mode === "edit"

  const selectedDays = useMemo(
    () => convertSchedulesToSelectedDays(data.transportSchedulesRepresentative),
    [data.transportSchedulesRepresentative],
  )

  const [isReduced, setIsReduced] = useState(true)

  const formik = useFormikContext<IPassengerList | AmendmentPassengerDetails>()
  const config = variantConfig[variant]
  const formikPath = config.formikPath

  const { autocompleteCircuits } = useCircuitStore()
  const [circuitOptions, setCircuitOptions] = useState<{ value: string; label: string }[]>([])

  useEffect(() => {
    const loadCircuits = async () => {
      try {
        const circuits = await autocompleteCircuits()
        const options = circuits.map((circuit: CircuitAutocompleteResponse) => ({
          value: circuit.id,
          label: circuit.circuitCode
        }))
        setCircuitOptions(options)
      } catch (error: any) {
        enqueueSnackbar(error.message, { variant: "error" })
      }
    }
    loadCircuits()
  }, [autocompleteCircuits])

  useEffect(() => {
    const transportSchedules = (formik.values as any)[formikPath][tabIndex]?.transportSchedulesRepresentative
    if (!transportSchedules || transportSchedules.length === 0) {
      const defaultSelectedDays = convertSchedulesToSelectedDays([])
      updateSelectedDays(defaultSelectedDays)
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [(formik.values as any)[formikPath][tabIndex]?.transportSchedulesRepresentative])

  const getAddressByType = useCallback(
    (type: AddressType) => {
      return data.addresses.find((addr) => addr.addressType === type) || ({} as Address)
    },
    [data.addresses],
  )

  const formData = useMemo(
    () => ({
      ...data,
      additionalAddress: getAddressByType(AddressType.REPRESENTATIVE)?.additionalAddress || "",
      pickupAddress: getAddressByType(AddressType.PICKUP)?.additionalAddress || "",
      circuitId: data.circuitId || "",
      mobile: data.contacts[0]?.mobilePhoneNumbers?.length > 0 ? data.contacts[0].mobilePhoneNumbers : [""],
      fixe: data.contacts[0]?.landlinePhoneNumbers?.length > 0 ? data.contacts[0].landlinePhoneNumbers : [""],
      personne: data.contacts[0]?.assignedPersonNames?.length > 0 ? data.contacts[0]?.assignedPersonNames : [""],
      notificationArivee: data.arrivalNotification,
      autorisationParentale: data.parentalAuthorization,
    }),
    [data, getAddressByType],
  )

  const { fields, handleAdd, handleDelete, handleChange } = useMultipleFields({
    initialValues: {
      mobile: formData.mobile,
      fixe: formData.fixe,
      personne: formData.personne,
    },
    onChange: (type, newValues) => {
      const updatedData: Partial<Representative> = {
        ...data,
        contacts: [
          {
            ...data.contacts[0],
            [type === "mobile"
              ? "mobilePhoneNumbers"
              : type === "fixe"
                ? "landlinePhoneNumbers"
                : "assignedPersonNames"]: newValues,
          },
        ],
      }
      onChange(updatedData)
    },
    isReadOnly,
  })

  const updateSelectedDays = useCallback(
    (newSchedule: SelectedDaysType) => {
      const updatedData: Partial<Representative> = {
        ...data,
        transportSchedulesRepresentative: convertSelectedDaysToSchedules(newSchedule),
      }
      onChange(updatedData)
    },
    [data, onChange],
  )

  const handleSelectionChange = useCallback(
    ({
      week,
      day,
      type,
      checked,
    }: {
      week: "pair" | "impair"
      day: string
      type: "all" | "ret"
      checked: boolean
    }) => {
      if (!isReadOnly && !isEditMode) {
        const newSchedule = {
          ...selectedDays,
          [week]: {
            ...selectedDays[week],
            [day]: {
              ...selectedDays[week]?.[day],
              [type]: checked,
            },
          },
        }
        updateSelectedDays(newSchedule)
      }
    },
    [isReadOnly, selectedDays, updateSelectedDays],
  )

  const getFieldError = useCallback(
    (fieldName: string) => {
      let fieldPath: string
      if (fieldName === "addresses") {
        const addressIndex =
          (formik.values as any)[formikPath]?.[tabIndex]?.addresses?.findIndex(
            (addr: Address) => addr.addressType === AddressType.REPRESENTATIVE,
          ) ?? -1
        fieldPath = `${formikPath}[${tabIndex}].addresses${addressIndex >= 0 ? `[${addressIndex}].additionalAddress` : ""}`
      } else {
        fieldPath = `${formikPath}[${tabIndex}].${fieldName}`
      }
      const touched = getIn(formik.touched, fieldPath)
      const error = getIn(formik.errors, fieldPath)
      return touched && error ? String(error) : undefined
    },
    [formik.touched, formik.errors, formik.values, tabIndex, formikPath],
  )

  const handleFieldChange = useCallback(
    (name: string, value: any) => {
      if (name === "addresses" || name === "pickupAddress") {
        const addressType = name === "pickupAddress" ? AddressType.PICKUP : AddressType.REPRESENTATIVE
        const addressData: Address = {
          additionalAddress: value.address || "",
          latitude: value.lat || 0,
          longitude: value.lng || 0,
          city: value.city || "",
          zipCode: value.zipCode || "",
          country: value.country || "",
          addressType: addressType,
        }
        const updatedAddresses = (data.addresses || []).reduce<Address[]>(
          (acc, currentAddr) => {
            if (currentAddr.addressType !== addressType) {
              acc.push(currentAddr)
            }
            return acc
          },
          [addressData],
        )
        const updatedData: Partial<Representative> = {
          ...data,
          addresses: updatedAddresses,
        }
        onChange(updatedData)
      } else {
        const updatedData: Partial<Representative> = {
          ...data,
          [name]: value,
        }
        onChange(updatedData)
      }
    },
    [data, onChange],
  )

  const renderField = useCallback(
    (field: FormFieldType<any>) => {
      const fieldName = field.name as string
      const error = getFieldError(fieldName)
      return (
        <FormField
          field={field}
          value={
            field.name === "circuitId"
              ? formData.circuitId :
            field.name === "addresses"
              ? formData.additionalAddress
              : field.name === "pickupAddress"
                ? formData.pickupAddress
                : (formData as any)[fieldName]
          }
          onChange={handleFieldChange}
          error={error}
          isReadOnly={
            (disabledFields.includes(field.name as string) && isEditMode && field.name !== "circuitCode") ||
            (field.name === "circuitCode" && isEditMode && circuitCode !== "" && circuitCode !== null) ||
            isReadOnly
          }
          isDrawerElement={true}
          onBlur={() => formik.setFieldTouched(`${formikPath}[${tabIndex}].${fieldName}`, true)}
        />
      )
    },
    [getFieldError, formData, handleFieldChange, isReadOnly, formik, tabIndex, isEditMode, formikPath],
  )

  const memoizedFormFields = useMemo(() => {
    return (
      <>
        {mainRepresentantformFields.map((field) => (
          <Grid item xs={12} sx={centerFlexColumn} sm={field.name === "civility" ? 8 : 4} key={field.name}>
            {renderField(field)}
          </Grid>
        ))}
      </>
    )
  }, [renderField])


  const lastFormFields = useMemo(() => {
    return (
      <>
        {contactFormFields(circuitOptions).map((field) => (
          <Grid item xs={12} sm={field.name === "arrivalNotification" ? 6 : 4} key={field.name}>
            {renderField(field)}
          </Grid>
        ))}
      </>
    )
  }, [renderField, circuitOptions])

  const renderPhoneFields = useMemo(() => {
    return ["mobilePhoneNumbers", "landlinePhoneNumbers", "assignedPersonNames"].map((type) => {
      const fieldType = typeMap[type as keyof typeof typeMap]
      const numbers = fields[fieldType] || []
      const field = contactsFormFields.find((f) => f.name === type)
      return numbers.map((number: string, index: number) => {
        const fieldPath = `${formikPath}[${tabIndex}].contacts[0].${type}[${index}]`
        const error =
          getIn(formik.errors, fieldPath) && getIn(formik.touched, fieldPath)
            ? String(getIn(formik.errors, fieldPath))
            : undefined
        return (
          <DuplicableField
            key={`${type}-${index}`}
            fieldType={fieldType}
            field={field!}
            index={index}
            value={number}
            isReadOnly={isReadOnly}
            onChange={handleChange}
            onAdd={handleAdd}
            onDelete={handleDelete}
            sx={{ display: "flex", flexDirection: "column" }}
            formData={formData}
            error={error}
            onBlur={() => formik.setFieldTouched(fieldPath, true)}
          />
        )
      })
    })
  }, [fields, isReadOnly, handleAdd, handleDelete, handleChange, formik, data, formData, tabIndex, formikPath])

  const handleToggleReduced = useCallback(() => {
    setIsReduced((prev) => !prev)
  }, [])

  return (
    <Box
      sx={{
        width: "100%",
        mb: 2,
        height: isReduced ? "80px" : "auto",
        overflow: isReduced ? "hidden" : "visible",
      }}
    >
      <Box sx={{ position: "absolute", bottom: 0, right: 0 }}>
        <Button
          endIcon={<FontAwesome icon={isReduced ? faAnglesDown : faAnglesUp} width={12} />}
          onClick={handleToggleReduced}
          variant="text"
          sx={{
            textTransform: "none",
            fontSize: pxToRem(13),
            "&:hover": {
              backgroundColor: "transparent",
            },
          }}
        >
          {isReduced ? "Voir plus" : "Réduire détails"}
        </Button>
      </Box>

      {/* Bouton de suppression conditionnel pour la variante amendment */}
      {variant === "amendment" && (
        <ConditionalComponent isValid={!isReadOnly && !withContact && !isReduced}>
          <Box sx={{ display: "flex", justifyContent: "flex-end", mb: 1 }}>
            <CustomTooltip title="Supprimer Adresse" arrow>
              <IconButton sx={iconButtonStyles} onClick={(e) => handleTabClose!(e, tabIndex)}>
                <FontAwesome icon={faSquareMinus} width={15} />
              </IconButton>
            </CustomTooltip>
          </Box>
        </ConditionalComponent>
      )}

      <Grid container spacing={2} sx={{ pt: 2 }}>
        {memoizedFormFields}
      </Grid>

      <Grid container spacing={2} sx={{ pt: 3 }}>
        {renderPhoneFields}
      </Grid>

      <Grid container spacing={2} sx={{ pt: 2 }}>
        {lastFormFields}
      </Grid>

      <ScheduleTable
        title="Trajets concernés"
        mode="checkbox"
        selectedDays={selectedDays}
        onSelectionChange={handleSelectionChange}
        isRepresentative={true}
      />
    </Box>
  )
}

export function RepresentantForm(props: Omit<StandardFormProps, "variant">) {
  return <UnifiedRepresentantForm {...props} variant="standard" />
}

export function AvenantRepresentantForm(props: Omit<AmendmentFormProps, "variant">) {
  return <UnifiedRepresentantForm {...props} variant="amendment" />
}
