import { Field, Label, Input as HeadlessInput } from '@headlessui/react'
import { CloudArrowUpIcon } from '@heroicons/react/20/solid'
import { useEffect, type ComponentProps, type ReactNode } from 'react'
import {
  get,
  type FieldError,
  type FieldValues,
  type Path,
  type RegisterOptions,
} from 'react-hook-form'
import { useRemixFormContext } from 'remix-hook-form'
import { twMerge } from 'tailwind-merge'

import { useAdminContext, type TUpload } from '~/contexts/admin'

import { Button } from './button'

type TInputProperties<T extends FieldValues> = Omit<
  ComponentProps<'input'>,
  'size'
> & {
  id: string
  label?: ReactNode
  name: Path<T>
  rules?: RegisterOptions
  containerClassName?: string
  labelClassName?: string
  category?: string
}

export const InputFile = <TFormValues extends Record<string, unknown>>(
  properties: TInputProperties<TFormValues>,
) => {
  const {
    id,
    label,
    name,
    rules,
    placeholder,
    disabled,
    className,
    containerClassName,
    labelClassName,
    category,
    ...restProperties
  } = properties
  const { setIsUploadOpen, uploadedFile, setUploadedFile, isUploadOpen } =
    useAdminContext()

  const {
    register,
    formState: { errors },
    setValue,
  } = useRemixFormContext()

  const error: FieldError = get(errors, name)

  useEffect(() => {
    if (uploadedFile && isUploadOpen === name) {
      setValue(name as string, uploadedFile)
      setUploadedFile(undefined)
      setIsUploadOpen(undefined)
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [uploadedFile])

  return (
    <Field
      className={twMerge('relative', containerClassName)}
      disabled={disabled}
      id={id}
    >
      <Label className={twMerge('mb-1 block text-gray-700', labelClassName)}>
        {label} {error && <span className="text-red-500">{error.message}</span>}
      </Label>
      <HeadlessInput
        className={twMerge(
          'h-[42px] w-full rounded-md border border-[#DFDFDF] p-2 pr-8',
          className,
        )}
        placeholder={placeholder}
        {...register(name, rules)}
        {...restProperties}
      />
      <Button
        type="button"
        variant="icon"
        size="fit"
        className="absolute right-3 h-[42px]"
        onClick={() => {
          setIsUploadOpen((category || name) as TUpload)
        }}
      >
        <CloudArrowUpIcon className="h-4 w-4 text-gray-500/50" />
      </Button>
    </Field>
  )
}
