// frontend\src\components\ui\TextInput.tsx

'use client'

import {
  useRef,
  useCallback,
  forwardRef,
  type InputHTMLAttributes,
  type Ref,
} from 'react'

type TextInputSize = 'sm' | 'md' | 'lg'

export type TextInputProps = Omit<
  InputHTMLAttributes<HTMLInputElement>,
  'size'
> & {
  size?: TextInputSize
  selectAllOnFocus?: boolean
  selectAllOnMouseDown?: boolean
}

const baseClassName = `
  block w-full min-w-0
  bg-white text-gray-900 shadow-sm ring-1 ring-gray-200
  focus:outline-none focus:ring-2 focus:ring-indigo-500
  dark:bg-white/10 dark:text-white dark:ring-white/10 dark:[color-scheme:dark]
`

const sizeClassName: Record<TextInputSize, string> = {
  sm: 'rounded-md px-3 py-2 text-sm',
  md: 'rounded-lg px-3 py-2.5 text-sm',
  lg: 'rounded-lg px-4 py-3 text-base',
}

function assignRef<T>(ref: Ref<T> | undefined, value: T | null) {
  if (!ref) return

  if (typeof ref === 'function') {
    ref(value)
    return
  }

  ;(ref as { current: T | null }).current = value
}

const TextInput = forwardRef<HTMLInputElement, TextInputProps>(
  (
    {
      className = '',
      type = 'text',
      size = 'md',
      selectAllOnFocus = false,
      selectAllOnMouseDown = false,
      onFocus,
      onMouseDown,
      ...props
    },
    forwardedRef
  ) => {
    const innerRef = useRef<HTMLInputElement | null>(null)

    const setRefs = useCallback(
      (node: HTMLInputElement | null) => {
        innerRef.current = node
        assignRef(forwardedRef, node)
      },
      [forwardedRef]
    )

    const selectAll = useCallback(() => {
      const el = innerRef.current
      if (!el) return
      el.focus()
      requestAnimationFrame(() => el.select())
    }, [])

    return (
      <input
        {...props}
        ref={setRefs}
        type={type}
        className={[baseClassName, sizeClassName[size], className].join(' ').trim()}
        onFocus={(e) => {
          onFocus?.(e)
          if (selectAllOnFocus) {
            selectAll()
          }
        }}
        onMouseDown={(e) => {
          onMouseDown?.(e)

          if (!selectAllOnMouseDown) return
          if (e.button !== 0) return

          e.preventDefault()
          selectAll()
        }}
      />
    )
  }
)

TextInput.displayName = 'TextInput'

export default TextInput