import type { FC } from 'react';
import React from 'react';
import { GlyphIcon } from '@theorchard/suite-icons';
import cx from 'classnames';
import { Form } from 'react-bootstrap';

const CLASS_NAME = 'NumberInput';

export interface Props {
    className?: string;
    style?: React.CSSProperties;
    testId?: string;
    value: string;
    onChange: (val: string) => void;
    allowNegatives?: boolean;
    disabled?: boolean;
    placeholder?: string;
    decimalPrecision?: number;
}

/**
 * NumberInput is a form input element that only accepts numerical values. It includes up and down arrows to increase and decrease the number value.
 *
 * @type atom
 * @status revised
 * @tags form-elements
 */
export const NumberInput: FC<Props> = ({
    className,
    style,
    testId = CLASS_NAME,
    value,
    onChange,
    disabled = false,
    allowNegatives = true,
    decimalPrecision = 0,
    placeholder = '',
}) => {
    const setDecimal = (decimalParts: string[]) => {
        const wholeNumber = parseInt(decimalParts[0], 10);

        if (decimalParts[1] === '') onChange(`${wholeNumber.toString()}.`);
        else {
            const decimal = decimalParts[1].replace(/[^0-9]/g, '').substring(0, decimalPrecision);
            onChange(`${wholeNumber.toString()}.${decimal}`);
        }
    };

    const setValue = (val: string) => {
        const newVal = parseInt(val, 10);
        const decimalParts = val.split('.');
        if (val === '' || (allowNegatives && val === '-')) onChange(val);
        else if (decimalPrecision > 0 && decimalParts.length > 1) setDecimal(decimalParts);
        else if (!Number.isNaN(newVal)) onChange(newVal.toString());
    };

    const incrementValue = (incr: number) => {
        if (disabled) return;
        const currentVal = value === '' || value === '-' ? 0 : parseInt(value, 10);
        const newVal = currentVal + incr;
        if (allowNegatives || newVal >= 0) onChange(newVal.toString());
    };

    return (
        <div className={cx(CLASS_NAME, className)} style={style} data-testid={testId}>
            <Form.Control
                type="text"
                value={value}
                onChange={(e) => setValue(e.target.value)}
                disabled={disabled}
                placeholder={placeholder}
            />
            <div className="NumberInput-arrows">
                <div
                    role="button"
                    tabIndex={0}
                    onClick={() => incrementValue(1)}
                    onKeyPress={() => incrementValue(1)}
                >
                    <GlyphIcon name="caretUp" size={12} />
                </div>
                <div
                    role="button"
                    tabIndex={0}
                    onClick={() => incrementValue(-1)}
                    onKeyPress={() => incrementValue(-1)}
                >
                    <GlyphIcon name="caretDown" size={12} />
                </div>
            </div>
        </div>
    );
};
