'use client';

import type React from 'react';
import { useCallback, useMemo, useState } from 'react';
import { Grid, Button, IconButton } from '@mui/material';
import type { FormFieldType } 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, faPenToSquare } from '@fortawesome/free-solid-svg-icons';
import {
  contactFormFields,
  contactsFormFields,
  mainRepresentantformFields,
} from '../../../utils/form-fields-representative';
import { Box } from '@mui/system';
import CustomTooltip from '@/shared/components/tooltips/tooltip-custom';
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 ConditionalComponent from '@/shared/components/table/ConditionalComponent';
import type { Representative, IPassengerList } from '@/shared/types/passenger';
import { convertSchedulesToSelectedDays, convertSelectedDaysToSchedules } from '../../../utils/schedule-converters';
import { Address, AddressType } from '@/shared/types/establishment';
import { SelectedDaysType } from '@/shared/types/usager';
import ActionButtons from '@/shared/components/form/buttons-action';
import { mainColor, outlinedColor } from '@/shared/components/table/styles';
import { StyledCircularProgress } from '@/shared/components/form/style';

interface RepresentantFormProps {
  data: Representative;
  isReadOnly: boolean;
  withContact?: boolean;
  onChange: (newData: Partial<Representative>) => void;
  handleEdit?: () => void;
  handleTabClose: (event: React.MouseEvent) => void;
  onSave: () => void;
  tabIndex: number;
  loading?: boolean;
}

const typeMap = {
  mobilePhones: "mobile",
  landlinePhones: "fixe",
  assignedPersons: "personne",
} as const

export default function RepresentantForm({
  data,
  isReadOnly,
  onChange,
  handleEdit,
  handleTabClose,
  onSave,
  withContact,
  tabIndex,
  loading,
}: RepresentantFormProps) {
  const [selectedDays, setSelectedDays] = useState<SelectedDaysType>(convertSchedulesToSelectedDays(data.transportSchedules))
  const [isReduced, setIsReduced] = useState(true)
  const formik = useFormikContext<IPassengerList>()

  const formData = useMemo(
    () => ({
      ...data,
      address: data.addresses[0]?.additionalAddress || "",
      additionalAddress: data.addresses[0]?.additionalAddress || "",
      circuit: data.circuitCode || "",
      mobile: data.contacts[0]?.mobilePhones || [""],
      fixe: data.contacts[0]?.landlinePhones || [""],
      personne: data.contacts[0]?.assignedPersons || [""],
      notificationArivee: data.arrivalNotification,
      autorisationParentale: data.parentalAuthorization,
    }),
    [data],
  )

  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" ? "mobilePhones" : type === "fixe" ? "landlinePhones" : "assignedPersons"]: newValues,
          },
        ],
      }
      onChange(updatedData)
    },
    isReadOnly,
  })

  const handleSelectionChange = useCallback(
    ({
      week,
      day,
      type,
      checked,
    }: {
      week: "pair" | "impair"
      day: string
      type: "all" | "ret"
      checked: boolean
    }) => {
      if (!isReadOnly) {
        const newSchedule = {
          ...selectedDays,
          [week]: {
            ...selectedDays[week],
            [day]: {
              ...selectedDays[week]?.[day],
              [type]: checked,
            },
          },
        }
        setSelectedDays(newSchedule)
        const updatedData: Partial<Representative> = {
          ...data,
          transportSchedules: convertSelectedDaysToSchedules(newSchedule),
        }
        onChange(updatedData)
      }
    },
    [isReadOnly, selectedDays, data, onChange],
  )

  const getFieldError = useCallback((fieldName: string) => {
    let fieldPath: string;
  
    if (fieldName === "addresses") {
      fieldPath = `representatives[${tabIndex}].addresses[0].additionalAddress`;
    } else {
      fieldPath = `representatives[${tabIndex}].${fieldName}`;
    }
      const touched = getIn(formik.touched, fieldPath)
      const error = getIn(formik.errors, fieldPath)
      
      return touched && error ? String(error) : undefined
    },
    [formik.touched, formik.errors, tabIndex],
  )

  const handleFieldChange = useCallback(
    (name: string, value: any) => {
      if (name === "addresses") {
        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.REPRESENTATIVE,
        };
        const updatedData: Partial<Representative> = {
          ...data,
          addresses: [addressData],
        }
        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 === "addresses" ? formData.additionalAddress : (formData as any)[fieldName]}
          onChange={handleFieldChange}
          error={error}
          isReadOnly={isReadOnly}
          isDrawerElement={true}
          onBlur={() => formik.setFieldTouched(`representatives[${tabIndex}].${fieldName}`, true)}
        />
      )
    },
    [getFieldError, formData, handleFieldChange, isReadOnly, formik, tabIndex],
  )

  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(() => {
    const fieldsToRender = !withContact
      ? contactFormFields.filter((field) => field.name === "circuitCode" || field.name === "addresses")
      : contactFormFields

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

  const renderPhoneFields = useMemo(() => {
    return ["mobilePhones", "landlinePhones", "assignedPersons"].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 = `representatives[${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])

  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>
      <ConditionalComponent isValid={isReadOnly && !!handleEdit && !isReduced}>
        <Box sx={{ display: "flex", justifyContent: "flex-end", mb: 1 }}>
          <CustomTooltip title="Modifier Adresse" arrow>
            <IconButton sx={iconButtonStyles} onClick={handleEdit}>
              <FontAwesome icon={faPenToSquare} width={15} />
            </IconButton>
          </CustomTooltip>
        </Box>
      </ConditionalComponent>

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

      <ConditionalComponent isValid={!!withContact}>
        <Grid container spacing={2} sx={{ pt: 3 }}>
          {renderPhoneFields}
        </Grid>
      </ConditionalComponent>

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

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

      <ConditionalComponent isValid={!isReadOnly && !!handleEdit}>
        <Grid item xs={12} sx={{ pt: 2 }}>
          <Box display="flex" justifyContent="flex-end" gap={2}>
            <Button
              variant="outlined"
              onClick={handleTabClose}
              sx={{
                textTransform: "none",
                ...outlinedColor
              }}
            >
              Annuler
            </Button>
            <ConditionalComponent isValid={!!loading}>
              <StyledCircularProgress size={20} color="inherit"/>
            </ConditionalComponent>
            <Button
              onClick={onSave}
              variant="contained"
              sx={{
                boxShadow: "none",
                textTransform: "none",
                ...mainColor
              }}
              disabled={loading}
            >
              Enregistrer
            </Button>
          </Box>
        </Grid>
      </ConditionalComponent>
    </Box>
  )
}
