import { Field, Label, Input as HeadlessInput } from '@headlessui/react'
import { useState, 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 { EyeIcon } from '~/components/icons/eye'

import { Button } from './button'

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

export const Input = <TFormValues extends Record<string, unknown>>(
  properties: TInputProperties<TFormValues>,
) => {
  const {
    id,
    label,
    name,
    rules,
    type = 'text',
    placeholder,
    disabled,
    ...rest
  } = properties
  const [inputType, setInputType] = useState(type)

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

  const error: FieldError = get(errors, name)

  return (
    <Field
      className="relative"
      disabled={disabled}
      id={id}
    >
      <Label className="mb-1 block text-gray-700">
        {label} {error && <span className="text-red-500">{error.message}</span>}
      </Label>
      <HeadlessInput
        type={inputType}
        className="h-[42px] w-full rounded-md border border-[#DFDFDF] p-2"
        placeholder={inputType === 'password' ? '******' : placeholder}
        {...register(name, rules)}
        {...rest}
      />
      {type === 'password' && (
        <Button
          type="button"
          variant="icon"
          size="fit"
          className="absolute right-3 h-[42px] text-gray-500"
          onClick={() =>
            setInputType(inputType === 'password' ? 'text' : 'password')
          }
        >
          <EyeIcon
            className={twMerge(
              'h-4 w-4',
              inputType === 'password' ? 'text-gray-500/50' : 'text-gray-500',
            )}
          />
        </Button>
      )}
    </Field>
  )
}
