import * as React from 'react';
import { clsx } from 'clsx';
import { Search, X } from 'lucide-react';

export interface SearchInputProps extends Omit<
  React.InputHTMLAttributes<HTMLInputElement>,
  'onChange' | 'value' | 'size'
> {
  /** Controlled value. */
  value: string;
  /** Called with the new value on every keystroke. */
  onChange: (next: string) => void;
  /** Placeholder text. Defaults to `Search…`. */
  placeholder?: string;
  /** When true, the clear-`x` button is visible while `value` is non-empty. */
  clearable?: boolean;
  /** Optional slot rendered below the input — typically `<SuggestionList>`. */
  suggestions?: React.ReactNode;
  /** Accessible label; required if `placeholder` is the only context. */
  ariaLabel?: string;
  /** Size scale. */
  size?: 'sm' | 'md' | 'lg';
  className?: string;
}

/**
 * `<SearchInput>` — themed search field with a leading icon, a clear-`x`
 * affordance, and an optional suggestions slot below.
 *
 * Avoids the `bl-search-bespoke` proliferation — Wave 9.D.4 consolidates
 * every product's hand-rolled search field into one accessible primitive.
 */
export const SearchInput = React.forwardRef<HTMLInputElement, SearchInputProps>(
  (
    {
      value,
      onChange,
      placeholder = 'Search…',
      clearable = true,
      suggestions,
      ariaLabel,
      size = 'md',
      className,
      ...rest
    },
    ref
  ) => {
    const heightCls: Record<NonNullable<SearchInputProps['size']>, string> = {
      sm: 'h-8 text-xs',
      md: 'h-10 text-sm',
      lg: 'h-12 text-base',
    };
    const iconBox: Record<NonNullable<SearchInputProps['size']>, string> = {
      sm: 'h-3.5 w-3.5',
      md: 'h-4 w-4',
      lg: 'h-5 w-5',
    };
    return (
      <div className={clsx('flex flex-col gap-1.5', className)} data-testid="bl-search-input">
        <div className="relative flex items-center">
          <Search
            className={clsx(
              iconBox[size],
              'pointer-events-none absolute left-3 text-[var(--bl-text-tertiary,#999)]'
            )}
            aria-hidden="true"
          />
          <input
            ref={ref}
            type="search"
            role="searchbox"
            value={value}
            onChange={e => onChange(e.target.value)}
            placeholder={placeholder}
            aria-label={ariaLabel ?? placeholder}
            className={clsx(
              heightCls[size],
              'w-full rounded-lg border bg-[var(--bl-surface-card,#fff)] pl-9 pr-9 outline-none transition',
              'border-[var(--bl-border,rgba(0,0,0,0.12))]',
              'placeholder:text-[var(--bl-text-tertiary,#999)]',
              'focus-visible:border-[var(--bl-accent,#6366f1)] focus-visible:ring-2 focus-visible:ring-[var(--bl-accent-muted,rgba(99,102,241,0.18))]'
            )}
            {...rest}
          />
          {clearable && value.length > 0 && (
            <button
              type="button"
              data-testid="bl-search-clear"
              aria-label="Clear search"
              onClick={() => onChange('')}
              className={clsx(
                'absolute right-2 grid place-items-center rounded-md p-1 text-[var(--bl-text-tertiary,#999)]',
                'transition hover:bg-[var(--bl-surface-muted,rgba(0,0,0,0.05))] hover:text-[var(--bl-text-primary,inherit)]'
              )}
            >
              <X className={iconBox[size]} aria-hidden="true" />
            </button>
          )}
        </div>
        {suggestions && <div data-testid="bl-search-suggestions">{suggestions}</div>}
      </div>
    );
  }
);

SearchInput.displayName = 'SearchInput';
