import {
  Controller,
  type FieldValues,
  type Path,
  type RegisterOptions,
  useFormContext,
} from "react-hook-form";

import { FileDropZone } from "../FileDropZone.tsx";

interface FileFieldProps<T extends FieldValues> {
  name: Path<T>;
  label?: string;
  hint?: string;
  showLimit?: boolean;
  disabled?: boolean;
  rules?: RegisterOptions<T, Path<T>>;
  /** Side effect run after the field value changes (e.g. derive a title). */
  onValueChange?: (file: File | null) => void;
}

/** `Controller`-wrapped {@link FileDropZone} bound to react-hook-form. */
export function FileField<T extends FieldValues>({
  name,
  label,
  hint,
  showLimit,
  disabled,
  rules,
  onValueChange,
}: FileFieldProps<T>) {
  const { control, formState: { errors } } = useFormContext<T>();
  const error = errors[name];

  return (
    <div className="form-field">
      {label && <span className="form-label">{label}</span>}
      <Controller
        name={name}
        control={control}
        rules={rules}
        render={({ field }) => (
          <FileDropZone
            file={(field.value as File | null) ?? null}
            onChange={(file) => {
              field.onChange(file);
              onValueChange?.(file);
            }}
            hint={hint}
            showLimit={showLimit}
            disabled={disabled}
          />
        )}
      />
      {error?.message && (
        <span className="form-hint form-hint--error">
          {String(error.message)}
        </span>
      )}
    </div>
  );
}
