import { cloneElement, isValidElement, useId, type ReactNode } from 'react';

import { cn } from '@/lib/utils';
import { Label } from '@/components/ui';

type ControlProps = { id?: string; 'aria-label'?: string; 'aria-describedby'?: string };

/**
 * A labelled control.
 *
 * The id is cloned onto the *control*, never onto a wrapper: a `<label for>`
 * pointing at a `<div>` associates with nothing, and the screen reader then
 * reads an unlabelled input. Four copies of this wrapper existed, two of them
 * byte-identical, and all four carried a subtler version of the same bug —
 * they gave the control `children.props.id ?? id` while pointing the label at
 * `id` unconditionally, so any control that already had an id of its own ended
 * up with a label addressing an element that did not exist.
 *
 * The hint is wired through `aria-describedby` rather than left as loose text
 * beneath, because a hint that only sighted users receive is not a hint, it is
 * decoration.
 */
export function FormField({
  label,
  hint,
  children,
  className,
}: {
  label: string;
  hint?: ReactNode;
  children: ReactNode;
  className?: string;
}) {
  const generated = useId();
  const hintId = `${generated}-hint`;

  const element = isValidElement<ControlProps>(children) ? children : null;
  const controlId = element?.props.id ?? generated;

  const control = element
    ? cloneElement(element, {
        id: controlId,
        // The visible label is the accessible name via `for`/`id`; the
        // `aria-label` is a belt-and-braces fallback for controls that render
        // a button rather than a form element (Radix Select, for one) where
        // `for` does not always carry.
        'aria-label': element.props['aria-label'] ?? label,
        'aria-describedby':
          hint == null ? element.props['aria-describedby'] : (element.props['aria-describedby'] ?? hintId),
      })
    : children;

  return (
    <div className={cn('flex min-w-0 flex-col gap-1.5', className)}>
      <Label as="label" htmlFor={controlId}>
        {label}
      </Label>
      {control}
      {hint == null ? null : (
        <p id={hintId} className="min-w-0 text-xs text-muted">
          {hint}
        </p>
      )}
    </div>
  );
}
