/** Field — a labelled wrapper for form controls with hint/error text (LD). */

import { useId } from "react";

import { cn } from "../lib/cn";

export interface FieldProps {
  /** Visible label text. */
  label: string;
  /** Optional helper text shown under the control. */
  hint?: string;
  /** Optional error message; when set, it replaces the hint and is announced. */
  error?: string;
  /** Visually hide the label (kept for screen readers). */
  hideLabel?: boolean;
  className?: string;
  /**
   * Render-prop receiving the generated `id` so the control can wire
   * `id`/`aria-describedby` to the label and message.
   */
  children: (props: { id: string; describedBy?: string }) => React.ReactNode;
}

/** Associates a label (and optional hint/error) with a single control. */
export function Field({ label, hint, error, hideLabel, className, children }: FieldProps) {
  const id = useId();
  const msgId = `${id}-msg`;
  const message = error ?? hint;

  return (
    <div className={cn("flex flex-col gap-1", className)}>
      <label
        htmlFor={id}
        className={cn(
          "text-xs font-medium text-muted",
          hideLabel && "sr-only",
        )}
      >
        {label}
      </label>
      {children({ id, describedBy: message ? msgId : undefined })}
      {message && (
        <p
          id={msgId}
          role={error ? "alert" : undefined}
          className={cn("text-xs", error ? "text-danger" : "text-faint")}
        >
          {message}
        </p>
      )}
    </div>
  );
}
