import { useRef, useState } from 'react';
import { getDisplayValue } from './utils.js';
import { isNotSafeValue } from '../amount-input/utils.js';
export const useNumberInput = ({ value, maxValue, minValue, step = 1, onChange, numericType, onBlur, trailingZeros = false, precision = 0, onFocus, }) => {
    const [isFocus, setIsFocus] = useState(false);
    const buttonRef = useRef(null);
    const canIncrement = maxValue !== undefined && (typeof value === 'bigint' ? value >= BigInt(maxValue) : Number(value) >= maxValue);
    const canDecrement = minValue !== undefined && (typeof value === 'bigint' ? value <= BigInt(minValue) : Number(value) <= minValue);
    const showSteps = isFocus;
    // Boolean to no convert float values to BigInt
    const isBigInt = numericType && numericType === 'BigInt';
    // Prevent to write invalid characters and handle the arrow keys
    const preventInvalidCharsAndHandleArrows = (e) => {
        if (['e', 'E', '+'].includes(e.key)) {
            e.preventDefault();
            return;
        }
        // Handle the arrow keys
        if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {
            e.preventDefault();
            const operation = e.key === 'ArrowUp' ? 'increment' : 'decrement';
            // Call the handleChangeSteps function
            stepValueHandler(e, operation);
        }
    };
    // Prevent pasting invalid characters
    const blockInvalidPaste = (e) => {
        const pastedData = e.clipboardData.getData('Text');
        if (/[eE]/.test(pastedData)) {
            e.preventDefault();
        }
    };
    // Avoid to write letters directly in safari
    const preventLetterInput = (event) => {
        const char = event.key;
        // Only prevent letters, allow all other characters
        if (/^[a-zA-Z]$/.test(char) && !(event.ctrlKey || event.metaKey)) {
            event.preventDefault();
        }
    };
    // Handle the step value
    const stepValueHandler = (e, operation) => {
        e.preventDefault();
        let newValue;
        if (isBigInt) {
            const currentValue = BigInt(value ?? 0);
            const adjustment = BigInt(step || 1) * (operation === 'increment' ? BigInt(1) : BigInt(-1));
            newValue = currentValue + adjustment;
        }
        else {
            const currentValue = Number(value ?? 0);
            const adjustment = (step || 1) * (operation === 'increment' ? 1 : -1);
            // Convertir a string con la precisión correcta y volver a número
            newValue = parseFloat((currentValue + adjustment).toFixed(precision || 10));
        }
        if (!isBigInt) {
            if (maxValue !== undefined && Number(newValue) > maxValue)
                return;
            if (minValue !== undefined && Number(newValue) < minValue)
                return;
        }
        const nativeEvent = new Event('change', {
            bubbles: true,
            cancelable: true,
        });
        Object.defineProperty(nativeEvent, 'target', {
            value: { value: newValue },
            writable: false,
        });
        onChange?.(nativeEvent);
    };
    const handleBlur = (e) => {
        setIsFocus(false);
        const inputValue = e.target.value;
        // If the value is not a number, not an empty string, or is empty, show the error message or keep it empty
        if (inputValue === '' || isNaN(Number(inputValue))) {
            onBlur?.(e);
            return;
        }
        const integerTypes = [
            'PositiveInt',
            'NegativeInt',
            'NonNegativeInt',
            'NonPositiveInt',
            'BigInt',
            'Int',
        ];
        // Get the formatted value for keeping the trailing zeros
        const formattedValue = getDisplayValue(inputValue, {
            numericType,
            precision,
            trailingZeros,
        });
        const isNotSafe = isNotSafeValue(inputValue);
        // Avoid converting an unsafe value to scientific notation
        if (isNotSafe) {
            onBlur?.(e);
            return;
        }
        const finalValue = !numericType || integerTypes.includes(numericType) ? parseFloat(inputValue).toString() : formattedValue;
        const nativeEvent = new Event('change', {
            bubbles: true,
            cancelable: true,
        });
        Object.defineProperty(nativeEvent, 'target', {
            value: { value: finalValue },
            writable: false,
        });
        onChange?.(nativeEvent);
        onBlur?.(e);
    };
    const handleFocus = (e) => {
        e.preventDefault();
        setIsFocus(true);
        onFocus?.(e);
    };
    return {
        canIncrement,
        canDecrement,
        showSteps,
        preventInvalidCharsAndHandleArrows,
        stepValueHandler,
        blockInvalidPaste,
        preventLetterInput,
        isBigInt,
        handleBlur,
        handleFocus,
        isFocus,
        buttonRef,
    };
};
//# sourceMappingURL=use-number-input.js.map