import React, { forwardRef, useId } from "react";
import FormField, { FormFieldProps } from "./form-field";
import { cn } from "~/lib/utils";
import { Controller, FieldValues, Path } from "react-hook-form";
import { useFormReturn } from "~/hooks/useForm";

export type SelectItem = {
  label: string;
  value: string;
};

type BaseSelectProps = React.ComponentPropsWithoutRef<"select"> &
  FormFieldProps & {
    inputClassName?: string;
    items?: SelectItem[] | null;
  };

const BaseSelect = forwardRef<HTMLSelectElement, BaseSelectProps>(
  (props, ref) => {
    const { className, label, error, inputClassName, items, ...restProps } =
      props;
    const id = useId();

    const input = (
      <select
        ref={ref}
        className={cn(
          "h-10 w-full rounded-md border border-slate-200 px-3 py-2 text-sm ring-offset-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-slate-950 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:border-white/40 bg-transparent dark:ring-offset-slate-950 dark:placeholder:text-slate-400 dark:focus-visible:ring-slate-300",
          inputClassName
        )}
        {...restProps}
      >
        {items?.map((item) => (
          <option key={item.value} value={item.value} className="text-gray-900">
            {item.label}
          </option>
        ))}
      </select>
    );

    if (label || error) {
      return (
        <FormField
          id={id}
          label={label}
          error={error}
          className={className}
          children={input}
        />
      );
    }

    return input;
  }
);

type SelectProps<T extends FieldValues> = Omit<
  BaseSelectProps,
  "form" | "name"
> & {
  form?: useFormReturn<T>;
  name?: Path<T>;
};

const Select = <T extends FieldValues>(props: SelectProps<T>) => {
  const { form, ...restProps } = props;

  if (form && props.name) {
    return (
      <Controller
        control={form.control}
        name={props.name}
        render={({ field, fieldState }) => (
          <BaseSelect
            {...restProps}
            {...field}
            value={field.value || ""}
            error={fieldState.error?.message}
          />
        )}
      />
    );
  }

  return <BaseSelect {...restProps} />;
};

export default Select;