// Formularelemente-Basis-Komponenten — SHL-01. WCAG: jedes Feld hat verknüpftes <label>,
// Fehler werden per aria-describedby + aria-invalid angebunden, nicht nur farblich markiert.

import { useId } from "react";
import type { InputHTMLAttributes, ReactNode, SelectHTMLAttributes } from "react";

interface FieldWrapperProps {
  label: string;
  error?: string;
  hint?: string;
  children: (ids: { inputId: string; describedBy: string | undefined }) => ReactNode;
}

function FieldWrapper({ label, error, hint, children }: FieldWrapperProps) {
  const inputId = useId();
  const hintId = hint ? `${inputId}-hint` : undefined;
  const errorId = error ? `${inputId}-error` : undefined;
  const describedBy = [hintId, errorId].filter(Boolean).join(" ") || undefined;

  return (
    <div className="shl-field">
      <label htmlFor={inputId}>{label}</label>
      {children({ inputId, describedBy })}
      {hint && (
        <p id={hintId} className="shl-field-hint">
          {hint}
        </p>
      )}
      {error && (
        <p id={errorId} className="shl-field-error" role="alert">
          {error}
        </p>
      )}
    </div>
  );
}

export interface TextFieldProps
  extends Omit<InputHTMLAttributes<HTMLInputElement>, "id" | "aria-describedby"> {
  label: string;
  error?: string;
  hint?: string;
}

export function TextField({ label, error, hint, ...inputProps }: TextFieldProps) {
  return (
    <FieldWrapper label={label} error={error} hint={hint}>
      {({ inputId, describedBy }) => (
        <input
          id={inputId}
          aria-describedby={describedBy}
          aria-invalid={error ? true : undefined}
          {...inputProps}
        />
      )}
    </FieldWrapper>
  );
}

export interface SelectFieldProps
  extends Omit<SelectHTMLAttributes<HTMLSelectElement>, "id" | "aria-describedby"> {
  label: string;
  error?: string;
  hint?: string;
  children: ReactNode;
}

export function SelectField({ label, error, hint, children, ...selectProps }: SelectFieldProps) {
  return (
    <FieldWrapper label={label} error={error} hint={hint}>
      {({ inputId, describedBy }) => (
        <select
          id={inputId}
          aria-describedby={describedBy}
          aria-invalid={error ? true : undefined}
          {...selectProps}
        >
          {children}
        </select>
      )}
    </FieldWrapper>
  );
}

export interface CheckboxFieldProps
  extends Omit<InputHTMLAttributes<HTMLInputElement>, "id" | "type"> {
  label: string;
}

export function CheckboxField({ label, ...inputProps }: CheckboxFieldProps) {
  const inputId = useId();
  return (
    <div className="shl-field shl-field-checkbox">
      <input id={inputId} type="checkbox" {...inputProps} />
      <label htmlFor={inputId}>{label}</label>
    </div>
  );
}
