import { forwardRef, useId, type InputHTMLAttributes } from 'react';

export interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
    label?: string;
    hint?: string;
    error?: string;
}

/**
 * Token-backed text input with a properly associated <label> and aria-describedby
 * for hint/error (fixes the unassociated-label a11y debt). Pass `error` to mark
 * the field invalid.
 */
export const Input = forwardRef<HTMLInputElement, InputProps>(function Input(
    { label, hint, error, id, className = '', ...rest },
    ref,
) {
    const autoId = useId();
    const inputId = id ?? autoId;
    const hintId = `${inputId}-hint`;
    const errorId = `${inputId}-error`;
    const describedBy = [hint ? hintId : null, error ? errorId : null].filter(Boolean).join(' ') || undefined;

    return (
        <div className="flex flex-col gap-1.5">
            {label ? (
                <label htmlFor={inputId} className="text-sm font-medium text-fg">
                    {label}
                </label>
            ) : null}
            <input
                ref={ref}
                id={inputId}
                aria-invalid={error ? true : undefined}
                aria-describedby={describedBy}
                className={`h-10 rounded-lg border bg-surface px-3 text-sm text-fg placeholder:text-muted focus:outline-none focus-visible:ring-2 focus-visible:ring-accent ${error ? 'border-danger' : 'border-border'} ${className}`}
                {...rest}
            />
            {hint && !error ? (
                <span id={hintId} className="text-xs text-muted">
                    {hint}
                </span>
            ) : null}
            {error ? (
                <span id={errorId} className="text-xs text-danger">
                    {error}
                </span>
            ) : null}
        </div>
    );
});
