/**
 * Number With Unit Input Component
 * A numeric input field with a unit selector dropdown
 */

import { ChevronDown } from 'lucide-react'
import { useState, useRef, useEffect } from 'react'

export type CSSUnit = 'px' | 'rem' | 'em' | 'vw' | 'vh' | '%'

const AVAILABLE_UNITS: CSSUnit[] = ['px', 'rem', 'em', 'vw', 'vh', '%']

interface NumberWithUnitInputProps {
    value: string
    onChange: (value: string) => void
    label?: string
    placeholder?: string
    min?: number
    max?: number
    step?: number
    disabled?: boolean
    className?: string
    allowedUnits?: CSSUnit[]
}

/**
 * Parse a CSS value string into number and unit parts
 * Examples: "16px" -> { value: 16, unit: "px" }
 *           "1.5rem" -> { value: 1.5, unit: "rem" }
 */
function parseValue(input: string | undefined | null): { value: number; unit: CSSUnit } {
    const safe = (typeof input === 'string' ? input : '').trim()
    const match = safe.match(/^(-?\d*\.?\d*)\s*(px|rem|em|vw|vh|%)?$/)
    if (match) {
        const num = parseFloat(match[1]) || 0
        const unit = (match[2] as CSSUnit) || 'px'
        return { value: num, unit }
    }
    return { value: 0, unit: 'px' }
}

export function NumberWithUnitInput({
    value,
    onChange,
    label,
    placeholder = '0',
    step = 1,
    disabled = false,
    className = '',
    allowedUnits = AVAILABLE_UNITS,
}: NumberWithUnitInputProps) {
    const { value: numericValue, unit } = parseValue(value)
    const [isOpen, setIsOpen] = useState(false)
    const dropdownRef = useRef<HTMLDivElement>(null)

    // Close dropdown when clicking outside
    useEffect(() => {
        const handleClickOutside = (event: MouseEvent) => {
            if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
                setIsOpen(false)
            }
        }
        document.addEventListener('mousedown', handleClickOutside)
        return () => document.removeEventListener('mousedown', handleClickOutside)
    }, [])

    const handleValueChange = (newValue: number) => {
        // NOTE: Do not clamp values here. Appearance style controls should not enforce min/max.
        onChange(`${newValue}${unit}`)
    }

    const handleUnitChange = (newUnit: CSSUnit) => {
        onChange(`${numericValue}${newUnit}`)
        setIsOpen(false)
    }

    return (
        <div className={`flex flex-col gap-1 ${className}`}>
            {label && (
                <label className="text-sm font-medium text-gray-700">
                    {label}
                </label>
            )}
            {/* Keep the unit/value pair visually consistent in RTL pages by rendering as: VALUE then UNIT (9999 | px) */}
            <div className="flex" dir="ltr">
                {/* Number input */}
                <input
                    type="number"
                    value={numericValue}
                    onChange={(e) => handleValueChange(parseFloat(e.target.value) || 0)}
                    onFocus={(e) => e.currentTarget.select()}
                    placeholder={placeholder}
                    step={step}
                    disabled={disabled}
                    className="
                        w-16 px-2 py-1.5 text-sm
                        border border-gray-300 rounded-l-md rounded-r-none
                        focus:ring-1 focus:ring-primary-500 focus:border-primary-500
                        disabled:bg-gray-100 disabled:cursor-not-allowed
                        text-left font-mono
                        [appearance:textfield]
                        [&::-webkit-outer-spin-button]:appearance-none
                        [&::-webkit-inner-spin-button]:appearance-none
                    "
                />

                {/* Unit selector dropdown */}
                <div className="relative" ref={dropdownRef}>
                    <button
                        type="button"
                        onClick={() => !disabled && setIsOpen(!isOpen)}
                        disabled={disabled}
                        className="
                            h-full px-2 py-1.5 text-sm
                            border border-gray-300 border-l-0
                            bg-gray-50 hover:bg-gray-100
                            rounded-r-md rounded-l-none
                            flex items-center gap-1
                            disabled:bg-gray-100 disabled:cursor-not-allowed
                            transition-colors
                        "
                    >
                        <span className="font-mono text-xs w-8 text-center">{unit}</span>
                        <ChevronDown className="w-3 h-3 text-gray-500" />
                    </button>

                    {isOpen && (
                        <div className="
                            absolute top-full left-0 mt-1 z-50
                            bg-white border border-gray-200 rounded-md shadow-lg
                            py-1 min-w-[72px]
                        ">
                            {allowedUnits.map((u) => (
                                <button
                                    key={u}
                                    type="button"
                                    onClick={() => handleUnitChange(u)}
                                    className={`
                                        w-full px-3 py-1.5 text-sm text-left
                                        hover:bg-gray-100 transition-colors
                                        ${u === unit ? 'bg-primary-50 text-primary-700 font-medium' : 'text-gray-700'}
                                    `}
                                >
                                    {u}
                                </button>
                            ))}
                        </div>
                    )}
                </div>
            </div>
        </div>
    )
}

export default NumberWithUnitInput

