import * as React from 'react'
import { cn } from '../lib/cn'

export interface InputProps
  extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'prefix'> {
  error?: string
  prefix?: React.ReactNode // icon/text inline-start of input
  suffix?: React.ReactNode // icon/text inline-end of input
  /**
   * Set `numeric` for fields that contain amounts (ILS), percentages, hours,
   * invoice numbers, phone numbers, or tax IDs (ח.פ. / ע.מ.).
   *
   * When true:
   * - Forces `dir="ltr"` on the <input> so digits read left-to-right even in an
   *   RTL document (Hebrew typography convention for numeric content).
   * - Sets `inputMode="decimal"` for a numeric keyboard on mobile.
   * - Keeps `type="text"` (never type="number" — that suppresses arrow-key
   *   navigation in some browsers and prevents custom formatting).
   * - Applies `.num` (text-align: end; font-variant-numeric: tabular-nums) so
   *   the value is end-aligned — visually right-aligned in both LTR and RTL.
   *
   * Note: the surrounding label, helper text, and error message continue to
   * inherit the document direction (RTL for Hebrew) — only the field value and
   * placeholder are forced LTR.
   */
  numeric?: boolean
}

/**
 * Text input with optional inline-start/inline-end slots (logical properties so
 * RTL flips correctly). Full a11y error wiring (aria-invalid / aria-describedby /
 * role=alert) is composed by FormField; a standalone `error` here only renders
 * the message and flags the field visually + via aria-invalid.
 *
 * For numeric inputs (amounts, percentages, invoice numbers, phone, tax IDs)
 * pass the `numeric` prop — this forces dir="ltr" and decimal inputMode so
 * digits read correctly in Hebrew RTL context.
 */
export const Input = React.forwardRef<HTMLInputElement, InputProps>(
  ({ className, error, prefix, suffix, type = 'text', numeric = false, ...props }, ref) => {
    // Numeric inputs: force LTR reading order regardless of document direction.
    // This matches Hebrew typographic conventions where numbers always read L→R.
    const numericProps = numeric
      ? ({
          dir: 'ltr',
          inputMode: 'decimal' as const,
          // type is kept as 'text' (never 'number') to preserve arrow-key navigation
        } satisfies Partial<React.InputHTMLAttributes<HTMLInputElement>>)
      : {}

    return (
      <div className="flex flex-col gap-2">
        <div
          className={cn(
            'flex items-center rounded border bg-surface text-ink',
            // 2px border is the tight-primitive exception (input border-width)
            error ? 'border-danger' : 'border-control-border',
            'focus-within:ring-2 focus-within:ring-focus-ring',
          )}
        >
          {prefix ? <span className="ps-2 text-ink-faint shrink-0">{prefix}</span> : null}
          <input
            ref={ref}
            type={type}
            aria-invalid={error ? true : undefined}
            className={cn(
              'h-8 w-full bg-transparent px-2 text-body-1 text-ink placeholder:text-ink-faint',
              'outline-none disabled:opacity-50',
              prefix && 'ps-2',
              suffix && 'pe-2',
              // numeric: end-align value + tabular figures (.num from rtl.css)
              numeric && 'num',
              className,
            )}
            {...numericProps}
            {...props}
          />
          {suffix ? (
            // Affordance icons (clear button, password eye toggle) are positioned
            // at inline-end via pe-2, which is a logical property and flips
            // automatically to the left side in RTL.
            <span className="pe-2 text-ink-faint shrink-0">{suffix}</span>
          ) : null}
        </div>
        {error ? (
          // Error message inherits document direction (RTL for Hebrew)
          <p role="alert" className="text-danger text-body-2">
            {error}
          </p>
        ) : null}
      </div>
    )
  },
)
Input.displayName = 'Input'
