import * as React from 'react'
import { useFormContext, get, type FieldError } from 'react-hook-form'
import { cn } from '../lib/cn'
import { FormLabel } from './form-label'
import { FormError } from './form-error'

export interface FormFieldProps {
  name: string
  label?: string
  required?: boolean
  className?: string
  /** Exactly one input element (Input, Select, Textarea, …). */
  children: React.ReactElement
}

/**
 * Composes label + input + error and AUTOMATICALLY wires WCAG error a11y onto
 * the child input (SC 1.3.1, SC 3.3.1):
 *   - registers the field with react-hook-form
 *   - sets aria-invalid when an error is present
 *   - sets aria-describedby -> `${name}-error` so the association persists on blur
 *   - renders the error in <p id role="alert"> for immediate SR announcement
 * Removing the error clears both aria-invalid and aria-describedby.
 * Error is conveyed by text (never color alone).
 */
export function FormField({ name, label, required, className, children }: FormFieldProps) {
  const { register, formState } = useFormContext()
  const error = get(formState.errors, name) as FieldError | undefined
  const errorId = `${name}-error`
  const fieldId = name

  const registration = register(name)
  const childRequired = (children.props as { required?: boolean }).required
  const effectiveRequired = childRequired ?? required

  const child = React.cloneElement(children, {
    ...registration,
    id: fieldId,
    required: effectiveRequired,
    'aria-invalid': error ? true : undefined,
    'aria-describedby': error ? errorId : undefined,
  } as Record<string, unknown>)

  return (
    <div className={cn('flex flex-col gap-2', className)}>
      {label ? (
        <FormLabel htmlFor={fieldId} required={effectiveRequired}>
          {label}
        </FormLabel>
      ) : null}
      {child}
      {error ? <FormError id={errorId}>{error.message}</FormError> : null}
    </div>
  )
}
