import { Heart, Sword } from "lucide-react";
import {
	useCallback,
	useEffect,
	useLayoutEffect,
	useRef,
	useState,
} from "react";
import { Input } from "./ui/input";

const DIGITS_ONLY_REGEX = /^\d+$/;

interface HpAdjustPopoverProps {
	readonly onAdjust: (delta: number) => void;
	readonly onClose: () => void;
}

export function HpAdjustPopover({ onAdjust, onClose }: HpAdjustPopoverProps) {
	const [inputValue, setInputValue] = useState("");
	const [pos, setPos] = useState<{ top: number; left: number } | null>(null);
	const ref = useRef<HTMLDivElement>(null);
	const inputRef = useRef<HTMLInputElement>(null);

	useLayoutEffect(() => {
		const el = ref.current;
		if (!el) return;
		const parent = el.parentElement;
		if (!parent) return;
		const trigger = parent.getBoundingClientRect();
		const popover = el.getBoundingClientRect();
		const vw = document.documentElement.clientWidth;
		let left = trigger.left;
		if (left + popover.width > vw) {
			left = vw - popover.width - 8;
		}
		if (left < 8) {
			left = 8;
		}
		setPos({ top: trigger.bottom + 4, left });
	}, []);

	useEffect(() => {
		requestAnimationFrame(() => inputRef.current?.focus());
	}, []);

	useEffect(() => {
		function handleClickOutside(e: MouseEvent) {
			if (ref.current && !ref.current.contains(e.target as Node)) {
				onClose();
			}
		}
		document.addEventListener("mousedown", handleClickOutside);
		return () => document.removeEventListener("mousedown", handleClickOutside);
	}, [onClose]);

	const parsedValue =
		inputValue === "" ? null : Number.parseInt(inputValue, 10);
	const isValid =
		parsedValue !== null && !Number.isNaN(parsedValue) && parsedValue > 0;

	const applyDelta = useCallback(
		(sign: -1 | 1) => {
			if (inputValue === "") return;
			const n = Number.parseInt(inputValue, 10);
			if (Number.isNaN(n) || n <= 0) return;
			onAdjust(sign * n);
			onClose();
		},
		[inputValue, onAdjust, onClose],
	);

	const handleKeyDown = useCallback(
		(e: React.KeyboardEvent<HTMLInputElement>) => {
			if (e.key === "Enter") {
				if (e.shiftKey) {
					applyDelta(1);
				} else {
					applyDelta(-1);
				}
			} else if (e.key === "Escape") {
				onClose();
			}
		},
		[applyDelta, onClose],
	);

	return (
		<div
			ref={ref}
			className="card-glow fixed z-10 rounded-lg border border-border bg-background p-2"
			style={
				pos
					? { top: pos.top, left: pos.left }
					: { visibility: "hidden" as const }
			}
		>
			<div className="flex items-center gap-1">
				<Input
					ref={inputRef}
					type="text"
					inputMode="numeric"
					value={inputValue}
					placeholder="HP"
					className="h-7 w-[7ch] text-center text-sm tabular-nums"
					onChange={(e) => {
						const v = e.target.value;
						if (v === "" || DIGITS_ONLY_REGEX.test(v)) {
							setInputValue(v);
						}
					}}
					onKeyDown={handleKeyDown}
				/>
				<button
					type="button"
					disabled={!isValid}
					className="inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-md text-red-400 transition-colors hover:bg-red-950 hover:text-red-300 disabled:pointer-events-none disabled:opacity-50"
					onClick={() => applyDelta(-1)}
					title="Apply damage"
					aria-label="Apply damage"
				>
					<Sword size={14} />
				</button>
				<button
					type="button"
					disabled={!isValid}
					className="inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-md text-emerald-400 transition-colors hover:bg-emerald-950 hover:text-emerald-300 disabled:pointer-events-none disabled:opacity-50"
					onClick={() => applyDelta(1)}
					title="Apply healing"
					aria-label="Apply healing"
				>
					<Heart size={14} />
				</button>
			</div>
		</div>
	);
}
