import { forwardRef, useEffect, useRef } from 'react';
import type { InputHTMLAttributes, ReactNode } from 'react';
import { cx } from '../../utils/cx';
import { useFallbackId } from '../../utils/useId';
import '../../styles/choice.css';
import './Checkbox.css';

export interface CheckboxProps
  extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type' | 'size'> {
  /** Text beside the box. */
  label?: ReactNode;
  /** Secondary line under the label. */
  description?: ReactNode;
  /** Renders the mixed state. Visual only — `checked` still drives the value. */
  indeterminate?: boolean;
  /** Puts the box in its invalid state. */
  invalid?: boolean;
}

/** Single checkbox with an optional label and description. */
export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(function Checkbox(
  { label, description, indeterminate = false, invalid = false, id, className, ...rest },
  ref,
) {
  const inputId = useFallbackId(id);
  const descriptionId = `${inputId}-description`;
  const innerRef = useRef<HTMLInputElement | null>(null);

  useEffect(() => {
    if (innerRef.current) innerRef.current.indeterminate = indeterminate;
  }, [indeterminate]);

  return (
    <div className={cx('ds-choice', 'ds-checkbox', invalid && 'ds-choice--invalid', className)}>
      <span className="ds-choice__control">
        <input
          {...rest}
          ref={(node) => {
            innerRef.current = node;
            if (typeof ref === 'function') ref(node);
            else if (ref) ref.current = node;
          }}
          id={inputId}
          type="checkbox"
          className="ds-choice__input"
          aria-invalid={invalid || undefined}
          aria-describedby={description != null ? descriptionId : undefined}
        />
        <span className="ds-choice__box ds-checkbox__box" aria-hidden="true">
          {indeterminate ? (
            <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="2">
              <path d="M4 8h8" strokeLinecap="round" />
            </svg>
          ) : (
            <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="2">
              <path d="M3.5 8.5l3 3 6-6" strokeLinecap="round" strokeLinejoin="round" />
            </svg>
          )}
        </span>
      </span>
      {(label != null || description != null) && (
        <span className="ds-choice__text">
          {label != null && (
            <label className="ds-choice__label" htmlFor={inputId}>
              {label}
            </label>
          )}
          {description != null && (
            <span id={descriptionId} className="ds-choice__description">
              {description}
            </span>
          )}
        </span>
      )}
    </div>
  );
});
