import { useId } from "react";
import * as LabelPrimitive from "@radix-ui/react-label";
import { cn } from "@/lib/utils";

/**
 * Field — groupe label + input + description + erreur.
 * Compose des primitives Radix Label pour l'a11y propre.
 *
 * Usage :
 *  <Field label="Email" hint="Pro de préférence" error={...}>
 *    <Input type="email" />
 *  </Field>
 *
 * Le children reçoit automatiquement `id` et `aria-invalid` via cloneElement-free
 * pattern : le `htmlFor` matche le `id` injecté dans children, mais on laisse
 * l'utilisateur passer son input pour rester explicite.
 */
type FieldProps = {
  label: string;
  /** Description courte sous le label (≠ erreur). */
  hint?: string;
  /** Message d'erreur — affiché en rubis-deep. */
  error?: string;
  /** ID custom (sinon généré). À passer aussi sur l'input enfant. */
  htmlFor?: string;
  /** Si true, label visuellement masqué (mais lu par les screen readers). */
  srOnlyLabel?: boolean;
  children: React.ReactNode;
  className?: string;
};

export function Field({
  label,
  hint,
  error,
  htmlFor,
  srOnlyLabel = false,
  children,
  className,
}: FieldProps) {
  const generatedId = useId();
  const id = htmlFor ?? generatedId;
  const hintId = hint ? `${id}-hint` : undefined;
  const errorId = error ? `${id}-error` : undefined;

  // Layout : label + hint en haut, input en bas. `mt-auto` sur le wrapper
  // de l'input le pousse au bas de la cellule. Quand plusieurs Fields sont
  // côte-à-côte dans une grille (ex. Téléphone + SIRET), un hint plus long
  // sur l'un n'écrase plus l'alignement des inputs : le label/hint d'un
  // côté étire le haut, l'input reste aligné avec ses voisins en bas.
  return (
    <div className={cn("flex flex-col h-full", className)}>
      <div className="flex flex-col gap-1.5">
        <LabelPrimitive.Root
          htmlFor={id}
          className={cn(
            "font-sans text-[13px] font-semibold text-ink",
            srOnlyLabel && "sr-only",
          )}
        >
          {label}
        </LabelPrimitive.Root>
        {hint && !error && (
          <p id={hintId} className="text-[12.5px] text-ink-3 leading-snug">
            {hint}
          </p>
        )}
      </div>
      <div className="mt-auto pt-1.5">
        <FieldContext.Provider
          value={{ id, describedBy: errorId ?? hintId, invalid: !!error }}
        >
          {children}
        </FieldContext.Provider>
        {error && (
          <p
            id={errorId}
            role="alert"
            className="mt-1.5 text-[12.5px] font-medium text-rubis-deep leading-snug"
          >
            {error}
          </p>
        )}
      </div>
    </div>
  );
}

import { createContext, useContext } from "react";

type FieldContextValue = {
  id: string;
  describedBy: string | undefined;
  invalid: boolean;
} | null;

const FieldContext = createContext<FieldContextValue>(null);

/**
 * Hook pour les inputs enfants : récupère id, aria-describedby, aria-invalid
 * depuis le Field parent. Permet d'éviter les props redondantes.
 */
export function useFieldContext(): NonNullable<FieldContextValue> {
  const ctx = useContext(FieldContext);
  if (!ctx) {
    throw new Error("useFieldContext doit être utilisé dans un <Field>");
  }
  return ctx;
}
