// @design-system: primitives/NumberInput
// Registered at /design-system#numberinput-primitive - Phase 3 (Agent 3E) will render the gallery.

import { forwardRef, useCallback } from 'react';
import { cn } from '@/lib/cn';
import { useT } from '@/lib/i18n/react';

/** Props for the NumberInput component */
export interface NumberInputProps extends Omit<
  React.InputHTMLAttributes<HTMLInputElement>,
  'type' | 'onChange'
> {
  /** Minimum allowed value. */
  min?: number;
  /** Maximum allowed value. */
  max?: number;
  /** Step increment. Defaults to 1. */
  step?: number;
  /** Current value (controlled). */
  value?: number;
  /** Change handler. */
  onChange?: (value: number) => void;
  /** When true, applies error styles. */
  invalid?: boolean;
}

/**
 * Multideal NumberInput - wraps an HTML number input with inc/dec buttons and arrow-key support.
 *
 * @example
 * ```tsx
 * <NumberInput min={1} max={100} value={qty} onChange={setQty} />
 * ```
 */
export const NumberInput = forwardRef<HTMLInputElement, NumberInputProps>(function NumberInput(
  { className, min, max, step = 1, value, onChange, invalid, disabled, ...props },
  ref,
) {
  const t = useT('common');
  const clamp = useCallback(
    (n: number) => {
      let v = n;
      if (min !== undefined) v = Math.max(min, v);
      if (max !== undefined) v = Math.min(max, v);
      return v;
    },
    [min, max],
  );

  const increment = useCallback(() => {
    if (disabled) return;
    onChange?.(clamp((value ?? 0) + step));
  }, [disabled, value, step, clamp, onChange]);

  const decrement = useCallback(() => {
    if (disabled) return;
    onChange?.(clamp((value ?? 0) - step));
  }, [disabled, value, step, clamp, onChange]);

  const handleKeyDown = useCallback(
    (e: React.KeyboardEvent<HTMLInputElement>) => {
      if (e.key === 'ArrowUp') {
        e.preventDefault();
        increment();
      } else if (e.key === 'ArrowDown') {
        e.preventDefault();
        decrement();
      }
    },
    [increment, decrement],
  );

  const handleChange = useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      const parsed = parseFloat(e.target.value);
      if (!isNaN(parsed)) onChange?.(clamp(parsed));
    },
    [clamp, onChange],
  );

  return (
    <div className={cn('flex items-center', className)}>
      <button
        type="button"
        aria-label={String(t('number_input_decrement'))}
        onClick={decrement}
        disabled={disabled || (min !== undefined && (value ?? 0) <= min)}
        className={cn(
          'flex h-10 w-10 shrink-0 items-center justify-center',
          'border-border-default bg-surface-base rounded-s-md border border-e-0',
          'text-text-muted text-lg',
          'hover:bg-neutral-50 active:bg-neutral-100',
          'disabled:cursor-not-allowed disabled:opacity-50',
          'focus-visible:ring-brand-primary-500 focus-visible:ring-2 focus-visible:ring-offset-1 focus-visible:outline-none',
          invalid && 'border-danger-500',
        )}
      >
        −
      </button>
      <input
        ref={ref}
        type="number"
        value={value}
        min={min}
        max={max}
        step={step}
        disabled={disabled}
        onChange={handleChange}
        onKeyDown={handleKeyDown}
        aria-invalid={invalid || undefined}
        className={cn(
          'border-border-default bg-surface-base w-full min-w-0 border-y text-center',
          'h-10 text-base text-neutral-900',
          'px-2 py-2',
          'focus:border-brand-primary-500 focus:ring-brand-primary-500/40 focus-visible:ring-2 focus:outline-none',
          'disabled:cursor-not-allowed disabled:bg-neutral-100 disabled:text-neutral-400',
          '[appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none',
          invalid && 'border-y-danger-500 focus:border-y-danger-500 focus:ring-danger-500/40',
        )}
        {...props}
      />
      <button
        type="button"
        aria-label={String(t('number_input_increment'))}
        onClick={increment}
        disabled={disabled || (max !== undefined && (value ?? 0) >= max)}
        className={cn(
          'flex h-10 w-10 shrink-0 items-center justify-center',
          'border-border-default bg-surface-base rounded-e-md border border-s-0',
          'text-text-muted text-lg',
          'hover:bg-neutral-50 active:bg-neutral-100',
          'disabled:cursor-not-allowed disabled:opacity-50',
          'focus-visible:ring-brand-primary-500 focus-visible:ring-2 focus-visible:ring-offset-1 focus-visible:outline-none',
          invalid && 'border-danger-500',
        )}
      >
        +
      </button>
    </div>
  );
});
