import type { HTMLAttributes, ReactNode } from 'react';
import { useId, useLayoutEffect, useRef } from 'react';
import './form-field-wrapper.css';

export type FormFieldState = 'default' | 'error' | 'success' | 'disabled';

export type FormFieldWrapperProps = {
  label?: string;
  required?: boolean;
  hint?: string;
  error?: string;
  state?: FormFieldState;
  /** If set, associates label and ARIA wiring with this id; otherwise a unique id is generated. */
  fieldId?: string;
  children?: ReactNode;
} & Omit<HTMLAttributes<HTMLDivElement>, 'children'>;

export function FormFieldWrapper({
  label = '',
  required = false,
  hint = '',
  error: errorText = '',
  state = 'default',
  fieldId: fieldIdProp,
  children,
  className,
  ...rest
}: FormFieldWrapperProps) {
  const uid = useId().replace(/:/g, '');
  const fieldId = fieldIdProp ?? `ccl-form-field-${uid}`;
  const hintId = `${fieldId}-hint`;
  const errorId = `${fieldId}-error`;
  const containerRef = useRef<HTMLDivElement>(null);

  const describedBy = [hint ? hintId : '', errorText || state === 'error' ? errorId : ''].filter(Boolean).join(' ');

  const isErrorState = state === 'error' || !!errorText;
  const isSuccessState = state === 'success' && !isErrorState;
  const isDisabledState = state === 'disabled';

  useLayoutEffect(() => {
    const root = containerRef.current;
    if (!root) return;
    const input = root.querySelector<HTMLElement>(
      '.ccl-form-field-wrapper__input-container input, .ccl-form-field-wrapper__input-container select, .ccl-form-field-wrapper__input-container textarea'
    );
    if (!input) return;
    if (!input.id) input.id = fieldId;
    if (describedBy) input.setAttribute('aria-describedby', describedBy);
    else input.removeAttribute('aria-describedby');
    if (required) input.setAttribute('aria-required', 'true');
    else input.removeAttribute('aria-required');
    if (isErrorState) input.setAttribute('aria-invalid', 'true');
    else input.removeAttribute('aria-invalid');
  }, [describedBy, fieldId, isErrorState, required, hint, errorText, state, children]);

  return (
    <div
      ref={containerRef}
      className={[
        'ccl-form-field-wrapper',
        isDisabledState ? 'ccl-form-field-wrapper--disabled' : '',
        isErrorState ? 'ccl-form-field-wrapper--error' : '',
        isSuccessState ? 'ccl-form-field-wrapper--success' : '',
        className ?? '',
      ]
        .filter(Boolean)
        .join(' ')}
      {...rest}
    >
      {label ? (
        <label htmlFor={fieldId} className="ccl-form-field-wrapper__label">
          {label}
          {required ? (
            <span className="ccl-form-field-wrapper__required" aria-label="required">
              *
            </span>
          ) : null}
        </label>
      ) : null}

      <div className="ccl-form-field-wrapper__input-container">{children}</div>

      {hint && !isErrorState ? (
        <span id={hintId} className="ccl-form-field-wrapper__hint">
          {hint}
        </span>
      ) : null}

      {errorText || isErrorState ? (
        <span id={errorId} className="ccl-form-field-wrapper__error" role="alert">
          {errorText}
        </span>
      ) : null}
    </div>
  );
}
