import { jsxs, jsx } from 'react/jsx-runtime';
import React__default, { useMemo, useEffect, useCallback } from 'react';
import { useReducedMotion, motion } from 'motion/react';
import { inputCounterTheme } from './InputCounter.theme.js';
import { Button } from '../../core/Button/Button.js';
import { SlidingNumber } from '../../core/SlidingNumber/SlidingNumber.js';
import { cn } from '../../../utils/cn.js';
import { MinusIcon, PlusIcon } from '@heroicons/react/24/outline';

/**
 * InputCounter component with animated number display
 *
 * Features:
 * - Increment/decrement buttons
 * - Smooth sliding number animation
 * - Min/max value constraints
 * - Custom step size (supports decimals)
 * - Keyboard support (Arrow Up/Down, Page Up/Down)
 * - Controlled component pattern
 *
 * @example
 * ```tsx
 * const [count, setCount] = useState(0);
 *
 * return (
 *   <InputCounter
 *     value={count}
 *     onChange={setCount}
 *     min={0}
 *     max={100}
 *     step={1}
 *   />
 * );
 * ```
 */
const InputCounter = React__default.forwardRef(({ value, onChange, min, max, step = 1, disabled = false, decimalPlaces, formatNumber = (n) => n.toString(), className, buttonProps, theme, transition = { type: "spring", bounce: 0, stiffness: 300, damping: 30 }, "aria-label": ariaLabel = "Counter", onAnimationStart, onAnimationEnd, onDrag, onDragStart, onDragEnd, ...props }, ref) => {
    const shouldReduceMotion = useReducedMotion();
    const shouldDisableAnimations = !!shouldReduceMotion;
    // Auto-detect decimal places from step if not explicitly provided
    const autoDecimalPlaces = useMemo(() => {
        if (decimalPlaces !== undefined)
            return decimalPlaces;
        if (!step)
            return 0;
        const stepStr = step.toString();
        const decimalIndex = stepStr.indexOf(".");
        if (decimalIndex === -1)
            return 0;
        return stepStr.length - decimalIndex - 1;
    }, [step, decimalPlaces]);
    // Merge theme overrides
    const mergedTheme = useMemo(() => ({
        ...inputCounterTheme,
        ...theme,
    }), [theme]);
    // Auto-clamp value to min/max bounds when they change
    useEffect(() => {
        let clampedValue = value;
        let needsUpdate = false;
        // Clamp to min
        if (min !== undefined && value < min) {
            clampedValue = min;
            needsUpdate = true;
        }
        // Clamp to max
        if (max !== undefined && value > max) {
            clampedValue = max;
            needsUpdate = true;
        }
        if (needsUpdate) {
            onChange(clampedValue);
        }
    }, [min, max, value, onChange]);
    // Handle increment
    const handleIncrement = useCallback(() => {
        if (disabled)
            return;
        const newValue = value + step;
        // Round to avoid floating point precision errors
        const decimalPlaces = Math.max((step.toString().split(".")[1] || "").length, (value.toString().split(".")[1] || "").length);
        const roundedValue = Number(newValue.toFixed(decimalPlaces));
        // Check max constraint
        if (max !== undefined && roundedValue > max) {
            if (process.env.NODE_ENV !== "production") {
                console.warn(`InputCounter: Cannot increment beyond max value (${max})`);
            }
            return;
        }
        onChange(roundedValue);
    }, [value, step, max, disabled, onChange]);
    // Handle decrement
    const handleDecrement = useCallback(() => {
        if (disabled)
            return;
        const newValue = value - step;
        // Round to avoid floating point precision errors
        const decimalPlaces = Math.max((step.toString().split(".")[1] || "").length, (value.toString().split(".")[1] || "").length);
        const roundedValue = Number(newValue.toFixed(decimalPlaces));
        // Check min constraint
        if (min !== undefined && roundedValue < min) {
            if (process.env.NODE_ENV !== "production") {
                console.warn(`InputCounter: Cannot decrement below min value (${min})`);
            }
            return;
        }
        onChange(roundedValue);
    }, [value, step, min, disabled, onChange]);
    // Keyboard support
    useEffect(() => {
        const handleKeyDown = (event) => {
            if (disabled)
                return;
            // Check if the counter is focused
            const target = event.target;
            if (!target.closest('[data-counter="true"]'))
                return;
            switch (event.key) {
                case "ArrowUp":
                    event.preventDefault();
                    handleIncrement();
                    break;
                case "ArrowDown":
                    event.preventDefault();
                    handleDecrement();
                    break;
                case "PageUp":
                    event.preventDefault();
                    const pageUpValue = value + step * 10;
                    if (max === undefined || pageUpValue <= max) {
                        onChange(pageUpValue);
                    }
                    else if (max !== undefined) {
                        onChange(max);
                    }
                    break;
                case "PageDown":
                    event.preventDefault();
                    const pageDownValue = value - step * 10;
                    if (min === undefined || pageDownValue >= min) {
                        onChange(pageDownValue);
                    }
                    else if (min !== undefined) {
                        onChange(min);
                    }
                    break;
            }
        };
        window.addEventListener("keydown", handleKeyDown);
        return () => window.removeEventListener("keydown", handleKeyDown);
    }, [
        value,
        step,
        min,
        max,
        disabled,
        onChange,
        handleIncrement,
        handleDecrement,
    ]);
    // Check if buttons should be disabled
    const canDecrement = !disabled && (min === undefined || value > min);
    const canIncrement = !disabled && (max === undefined || value < max);
    return (jsxs(motion.div, { ref: ref, "data-counter": "true", layout: true, transition: shouldDisableAnimations ? undefined : transition, className: cn(mergedTheme.baseStyle, className), role: "spinbutton", "aria-label": ariaLabel, "aria-valuenow": value, "aria-valuemin": min, "aria-valuemax": max, "aria-disabled": disabled, tabIndex: disabled ? -1 : 0, ...props, children: [jsx(motion.div, { className: mergedTheme.buttonWrapperStyle, whileHover: !disabled && !shouldDisableAnimations ? { scale: 1.05 } : undefined, whileTap: !disabled && !shouldDisableAnimations ? { scale: 0.95 } : undefined, children: jsx(Button, { size: "sm", variant: "link", iconOnly: true, ...buttonProps, onClick: handleDecrement, disabled: !canDecrement, "aria-label": "Decrement", children: jsx(MinusIcon, { className: "size-4 text-[var(--color-text-primary)]", strokeWidth: 2 }) }) }), jsx(SlidingNumber, { value: value, decimalPlaces: autoDecimalPlaces, className: mergedTheme.numberStyle, transition: transition }), jsx(motion.div, { className: mergedTheme.buttonWrapperStyle, whileHover: !disabled && !shouldDisableAnimations ? { scale: 1.05 } : undefined, whileTap: !disabled && !shouldDisableAnimations ? { scale: 0.95 } : undefined, children: jsx(Button, { size: "sm", variant: "link", iconOnly: true, ...buttonProps, onClick: handleIncrement, disabled: !canIncrement, "aria-label": "Increment", children: jsx(PlusIcon, { className: "size-4 text-[var(--color-text-primary)]", strokeWidth: 2 }) }) })] }));
});
InputCounter.displayName = "InputCounter";

export { InputCounter };
