/**
 * Custom Form Component: Numeric Input with Controls
 *
 * A numeric input field with increment/decrement buttons, validation,
 * and error display. Built on top of shadcn/ui components.
 *
 * @author Andreas Weyer
 * @license MIT
 */

import * as React from "react"
import { Minus, Plus, X } from "lucide-react"
import { Button } from "./button"
import { Input } from "./input"
import { cn } from "../../lib/utils"
import { useTranslation } from "react-i18next"

interface NumericInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'onChange' | 'value'> {
  value: string | number
  onChange: (value: string) => void
  increment?: number | string
  min?: number
  max?: number
  unit?: string
  align?: 'left' | 'center' | 'right'
  allowEmpty?: boolean
  clearButton?: boolean
  error?: boolean
  warning?: boolean
  required?: boolean
  errorMessage?: string
  warningMessage?: string
}

const FormNumericInput = React.forwardRef<HTMLInputElement, NumericInputProps>(
  ({
    value,
    onChange,
    increment = 1,
    min = -Infinity,
    max = Infinity,
    unit,
    align = 'right',
    allowEmpty = false,
    clearButton = false,
    error = false,
    warning = false,
    required = false,
    errorMessage = 'Time is required',
    warningMessage,
    className,
    ...props
  }, ref) => {
    const { t } = useTranslation()
    const [, setShowError] = React.useState(false)
    const [, setShowWarning] = React.useState(false)
    const [touched, setTouched] = React.useState(false)
    const [isFocused, setIsFocused] = React.useState(false)
    const containerRef = React.useRef<HTMLDivElement>(null)

    // Check if value is invalid (check validity regardless of touch state)
    const isInvalid = required && !allowEmpty && (value === '' || value === null || value === undefined)
    const hasError = error || isInvalid
    const hasWarning = warning && !hasError

    // Check validity on mount and when value changes
    React.useEffect(() => {
      if (isInvalid && touched) {
        setShowError(true)
      } else if (!isInvalid) {
        setShowError(false)
      }
    }, [isInvalid, touched])
    // Determine decimal places based on increment
    const getDecimalPlaces = () => {
      const inc = String(increment || '1')
      const decimalIndex = inc.indexOf('.')
      if (decimalIndex === -1) return 0
      return inc.length - decimalIndex - 1
    }

    const decimalPlaces = getDecimalPlaces()

    // Format value for display
    const formatValue = (val: string | number): string => {
      const num = Number(val)
      if (isNaN(num)) return String(val)
      return num.toFixed(decimalPlaces)
    }

    const updateValue = (direction: number) => {
      const numIncrement = parseFloat(String(increment)) || 1
      let numValue = Number(value)

      if (isNaN(numValue)) {
        numValue = 0
      }

      numValue += direction * numIncrement
      numValue = Math.max(min, numValue)
      numValue = Math.min(max, numValue)
      onChange(formatValue(numValue))
    }

    const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
      if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {
        e.preventDefault()
        updateValue(e.key === 'ArrowUp' ? 1 : -1)
      }
    }

    const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
      const val = e.target.value
      if (val === '' || /^-?\d*\.?\d*$/.test(val)) {
        onChange(val)
      }
    }

    const handleBlur = (e: React.FocusEvent<HTMLInputElement>) => {
      const inputValue = e.target.value.trim()
      setTouched(true)
      setIsFocused(false)
      setShowError(false)
      setShowWarning(false)

      if (inputValue === '' && !allowEmpty) {
        // Update parent with empty value so validation works
        onChange('')
        return
      }

      if (inputValue !== '' && !isNaN(Number(inputValue))) {
        onChange(formatValue(inputValue))
      }
    }

    const handleFocus = () => {
      setIsFocused(true)
      setShowError(hasError)
      setShowWarning(hasWarning)
    }

    const getAlignmentClass = () => {
      switch (align) {
        case 'left': return 'text-left'
        case 'center': return 'text-center'
        case 'right': return 'text-right'
        default: return 'text-right'
      }
    }

    return (
      <div ref={containerRef} className={cn("relative flex items-center gap-2", className)}>
        <div className="flex items-center">
          <Button
            type="button"
            variant="outline"
            size="icon"
            className={cn(
              "h-9 w-9 rounded-r-none border-r-0",
              hasError && "border-destructive",
              hasWarning && !hasError && "border-yellow-500"
            )}
            onClick={() => updateValue(-1)}
            tabIndex={-1}
          >
            <Minus className="h-4 w-4" />
          </Button>
          <Input
            ref={ref}
            type="text"
            value={value}
            onChange={handleChange}
            onBlur={handleBlur}
            onFocus={handleFocus}
            onKeyDown={handleKeyDown}
            className={cn(
              "w-20 h-9 z-20",
              "rounded-none",
              getAlignmentClass(),
              hasError && "border-destructive focus-visible:ring-destructive",
              hasWarning && !hasError && "border-yellow-500 focus-visible:ring-yellow-500"
            )}
            {...props}
          />
          <Button
            type="button"
            variant="outline"
            size="icon"
            className={cn(
              "h-9 w-9",
              clearButton && allowEmpty ? "rounded-l-none rounded-r-none border-x-0" : "rounded-l-none border-l-0",
              hasError && "border-destructive",
              hasWarning && !hasError && "border-yellow-500"
            )}
            onClick={() => updateValue(1)}
            tabIndex={-1}
          >
            <Plus className="h-4 w-4" />
          </Button>
          {clearButton && allowEmpty && (
            <Button
              type="button"
              variant="outline"
              size="icon"
              className={cn(
                "h-9 w-9 rounded-l-none",
                hasError && "border-destructive",
                hasWarning && !hasError && "border-yellow-500"
              )}
              onClick={() => onChange('')}
              tabIndex={-1}
              title={ t('buttonClear') }
            >
              <X className="h-4 w-4" />
            </Button>
          )}
        </div>
        {unit && <span className="text-sm text-muted-foreground whitespace-nowrap">{unit}</span>}
        {hasError && isFocused && errorMessage && (
          <div className="absolute top-full left-0 mt-1 z-50 w-64 bg-destructive text-destructive-foreground text-xs p-2 rounded-md shadow-lg">
            {errorMessage}
          </div>
        )}
        {hasWarning && isFocused && warningMessage && (
          <div className="absolute top-full left-0 mt-1 z-50 w-48 bg-yellow-500 text-white text-xs p-2 rounded-md shadow-lg">
            {warningMessage}
          </div>
        )}
      </div>
    )
  }
)

FormNumericInput.displayName = "FormNumericInput"

export { FormNumericInput }
