import { TextInput as AstryxTextInput } from '@astryxdesign/core/TextInput'
import { useId, type JSX, type ReactNode } from 'react'
import { FieldShell, type FieldLabelMode } from './internal/field'

export type TextFieldLabelMode = FieldLabelMode

export interface TextFieldProps {
  label: string
  value: string
  onValueChange(value: string): void
  labelMode?: TextFieldLabelMode
  hint?: string
  error?: string
  trailing?: ReactNode
  id?: string
  type?: 'text' | 'password' | 'email' | 'search' | 'number'
  placeholder?: string
  disabled?: boolean
  isDisabled?: boolean
  'data-testid'?: string
  autoComplete?: string
  maxLength?: number
  min?: number | string
  max?: number | string
  step?: number | string
  name?: string
  onKeyDown?: React.KeyboardEventHandler<HTMLInputElement>
  onFocus?: React.FocusEventHandler<HTMLInputElement>
  onBlur?: React.FocusEventHandler<HTMLInputElement>
}

export function TextField({
  label,
  value,
  onValueChange,
  labelMode = 'above',
  hint,
  error,
  trailing,
  id,
  type = 'text',
  isDisabled,
  disabled,
  ...rest
}: TextFieldProps): JSX.Element {
  const disabledState = isDisabled ?? disabled
  const needsShell = labelMode === 'inline' || trailing !== undefined
  const shellId = useId()
  const controlId = id ?? shellId
  const isSearch = type === 'search'
  const isNumber = type === 'number'
  const control = (
    <AstryxTextInput
      {...rest}
      id={controlId}
      type={isSearch || isNumber ? 'text' : type}
      role={isSearch ? 'searchbox' : undefined}
      label={label}
      isLabelHidden={needsShell ? true : labelMode === 'hidden'}
      value={value}
      isDisabled={disabledState}
      onChange={(next) => onValueChange(next)}
      description={hint}
      status={error !== undefined ? { type: 'error', message: error } : undefined}
    />
  )

  if (!needsShell) return control

  return (
    <FieldShell controlId={controlId} label={label} labelMode={labelMode} trailing={trailing}>
      {control}
    </FieldShell>
  )
}