import * as React from "react";
import useInterfaceSound from "@/hooks/useInterfaceSound";
import { InputText } from "./input-text";

type Props = Omit<
	React.ComponentProps<"input">,
	"value" | "onChange" | "type"
> & {
	value: number;
	onChange: (value: number) => void;
	min?: number;
	max?: number;
	step?: number | string;
};

const InputNumber = React.forwardRef<HTMLInputElement, Props>(
	({ value, onChange, min, max, onBlur, onFocus, ...rest }, ref) => {
		const [draft, setDraft] = React.useState<string>(String(value));
		const [focused, setFocused] = React.useState(false);

		React.useEffect(() => {
			if (!focused && String(value) !== draft) {
				setDraft(String(value));
			}
		}, [value, focused, draft]);

		const commit = (raw: string) => {
			if (raw === "" || raw === "-") return;
			const parsed = Number(raw);
			if (!Number.isFinite(parsed)) return;
			if (min !== undefined && parsed < min) return;
			if (max !== undefined && parsed > max) return;
			if (parsed !== value) onChange(parsed);
		};

		const { play } = useInterfaceSound();

		return (
			<InputText
				ref={ref}
				type="number"
				inputMode="numeric"
				min={min}
				max={max}
				value={draft}
				onFocus={(e) => {
					setFocused(true);
					play({ id: "click2" });
					onFocus?.(e);
				}}
				onChange={(e) => {
					const next = e.target.value;
					setDraft(next);
					commit(next);
				}}
				onBlur={(e) => {
					setFocused(false);
					const parsed = Number(draft);
					if (draft === "" || !Number.isFinite(parsed)) {
						setDraft(String(value));
					} else {
						let clamped = parsed;
						if (min !== undefined && clamped < min) clamped = min;
						if (max !== undefined && clamped > max) clamped = max;
						setDraft(String(clamped));
						if (clamped !== value) onChange(clamped);
					}
					onBlur?.(e);
				}}
				{...rest}
			/>
		);
	},
);
InputNumber.displayName = "InputNumber";

export { InputNumber };
