import { Field, Label, Select as HeadlessSelect } from '@headlessui/react'
import { type ComponentProps, type ReactNode } from 'react'
import {
  get,
  type FieldError,
  type FieldValues,
  type Path,
  type RegisterOptions,
  Controller,
} from 'react-hook-form'
import { useRemixFormContext } from 'remix-hook-form'
import { twMerge } from 'tailwind-merge'

type TSelectProperties<T extends FieldValues> = Omit<
  ComponentProps<'select'>,
  'size'
> & {
  id: string
  label?: ReactNode
  name: Path<T>
  rules?: RegisterOptions
  containerClassName?: string
  labelClassName?: string
  placeholder?: string
  options?: {
    name: string
    value: string | number
  }[]
}

export const Select = <TFormValues extends Record<string, unknown>>(
  properties: TSelectProperties<TFormValues>,
) => {
  const {
    id,
    label,
    name,
    rules,
    disabled,
    placeholder,
    options,
    className,
    labelClassName,
    containerClassName,
    ...restProperties
  } = properties
  const {
    control,
    formState: { errors },
  } = useRemixFormContext()

  const error: FieldError = get(errors, name)

  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>
      <Controller
        name={name}
        control={control}
        rules={rules}
        render={({ field }) => (
          <HeadlessSelect
            value={field.value}
            onChange={field.onChange}
            disabled={disabled}
            className={twMerge(
              'h-[42px] w-full rounded-md border border-[#DFDFDF] p-2',
              className,
            )}
            {...restProperties}
          >
            <option
              value=""
              disabled
              selected={!field.value}
            >
              {placeholder}
            </option>
            {options?.map(({ value, name }) => (
              <option
                key={value}
                value={value}
              >
                {name}
              </option>
            ))}
          </HeadlessSelect>
        )}
      />
    </Field>
  )
}
