import { memo, useState, useEffect } from "react";
import { Icon } from "@ax/components";

import * as S from "./style";

const NumberField = (props: INumberFieldProps) => {
	const { name, value, error, onChange, onBlur, maxValue, minValue, disabled, handleValidation, min, max } = props;

	const strValue = value || value === 0 ? value.toString() : "";
	const safeMax = typeof max !== "undefined" ? max : maxValue;
	const safeMin = typeof min !== "undefined" ? min : minValue;

	let validators: Record<string, unknown> = safeMax !== undefined ? { maxValue: safeMax } : {};
	validators = safeMin !== undefined ? { ...validators, minValue: safeMin } : validators;

	const [inputValue, setInputValue] = useState(strValue);

	useEffect(() => {
		setInputValue(strValue);
	}, [strValue]);

	const setValue = (value: string, eventType: string) => {
		const floatValue = value.length > 0 ? parseFloat(value) : undefined;
		setInputValue(value);

		eventType === "blur" ? onBlur?.(floatValue) : onChange(floatValue);
	};

	const handleClick = (pressedKey: string) => {
		const currentValue = parseFloat(inputValue);

		let updatedValue = !Number.isNaN(currentValue) ? currentValue : 0;
		const isMin = safeMin !== undefined && updatedValue === safeMin;
		const isMax = safeMax !== undefined && updatedValue === safeMax;

		if (pressedKey === "ArrowUp" && !isMax) {
			updatedValue++;
		} else if (pressedKey === "ArrowDown" && !isMin) {
			updatedValue--;
		}

		setInputValue(updatedValue.toString());
		onChange(updatedValue);
		handleValidation?.(updatedValue.toString(), validators);
	};

	const handleOnBlur = (e: React.FocusEvent<HTMLInputElement>) => {
		setValue(e.target.value, e.type);
		handleValidation?.(e.target.value, validators);
	};

	const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
		setValue(e.target.value, e.type);
		error && handleValidation?.(e.target.value, validators);
	};

	const increaseValue = () => handleClick("ArrowUp");
	const decreaseValue = () => handleClick("ArrowDown");

	return (
		<S.FieldWrapper error={error} data-testid="conditional-field-wrapper">
			<S.Input
				type="number"
				value={inputValue}
				name={name}
				onChange={handleChange}
				onBlur={handleOnBlur}
				error={error}
				min={safeMin}
				max={safeMax}
				disabled={disabled}
				data-testid="input"
			/>
			<S.QuantityNav error={error} disabled={disabled}>
				<S.ArrowUp onClick={disabled ? undefined : increaseValue} data-testid="arrow-up">
					<Icon name="UpArrow" />
				</S.ArrowUp>
				<S.ArrowDown onClick={disabled ? undefined : decreaseValue} data-testid="arrow-down">
					<Icon name="DownArrow" />
				</S.ArrowDown>
			</S.QuantityNav>
		</S.FieldWrapper>
	);
};

export interface INumberFieldProps {
	value?: number;
	onChange: (value: number | null | undefined) => void;
	name?: string;
	error?: boolean;
	minValue?: number; // to deprecate
	maxValue?: number; // to deprecate
	min?: number;
	max?: number;
	onBlur?: (value: number | null | undefined) => void;
	disabled?: boolean;
	handleValidation?: (value: string, validators: Record<string, unknown>) => void;
}

export default memo(NumberField);
