import { useEffect, useRef, useState } from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";

interface QrScannerProps {
	onScan: (token: string) => void;
	onCancel: () => void;
	/** When true the scanner takes up more vertical space (mobile full-screen mode) */
	fullHeight?: boolean;
}

export function QrScanner({ onScan, onCancel, fullHeight }: QrScannerProps) {
	const videoContainerId = "qr-video-container";
	const scannerRef = useRef<unknown>(null);
	const [hasError, setHasError] = useState(false);
	const [manualToken, setManualToken] = useState("");
	// Keep a stable ref so the effect never re-runs due to callback identity changes
	const onScanRef = useRef(onScan);
	useEffect(() => {
		onScanRef.current = onScan;
	}, [onScan]);

	useEffect(() => {
		let stopped = false;

		import("html5-qrcode")
			.then(({ Html5Qrcode }) => {
				if (stopped) return;

				const scanner = new Html5Qrcode(videoContainerId);
				scannerRef.current = scanner;

				scanner
					.start(
						{ facingMode: "environment" },
						{ fps: 15, qrbox: { width: 240, height: 240 } },
						(decodedText: string) => {
							// Stop immediately so we don't fire multiple times
							scanner
								.stop()
								.catch(console.error)
								.finally(() => {
									if (!stopped) onScanRef.current(decodedText);
								});
						},
						// Per-frame error (QR not found) — suppress
						() => {},
					)
					.catch((err: unknown) => {
						if (!stopped) {
							console.error("Camera start failed:", err);
							setHasError(true);
						}
					});
			})
			.catch((err) => {
				console.error("Failed to load html5-qrcode:", err);
				setHasError(true);
			});

		return () => {
			stopped = true;
			if (scannerRef.current) {
				(
					scannerRef.current as {
						stop: () => Promise<void>;
						clear: () => Promise<void>;
					}
				)
					.stop()
					.catch(() => {})
					.finally(() => {
						(scannerRef.current as { clear: () => Promise<void> })
							?.clear?.()
							.catch(() => {});
					});
			}
		};
	}, []); // runs once on mount

	const handleManualSubmit = () => {
		const token = manualToken.trim();
		if (token) onScan(token);
	};

	const containerHeight = fullHeight ? "h-64 sm:h-80" : "h-52";

	return (
		<div className="space-y-4">
			{!hasError ? (
				<div
					id={videoContainerId}
					className={`w-full overflow-hidden rounded-xl bg-black ${containerHeight} [&_#qr-shaded-region]:!border-white/30 [&>video]:h-full [&>video]:w-full [&>video]:object-cover`}
				/>
			) : (
				<div className="rounded-xl border border-white/10 bg-white/5 p-6 text-center">
					<p className="text-sm text-white/60">
						Camera niet beschikbaar. Plak het QR-token hieronder.
					</p>
				</div>
			)}

			{/* Manual fallback */}
			<div>
				<p className="mb-2 text-white/40 text-xs">Of plak token handmatig:</p>
				<div className="flex gap-2">
					<Input
						value={manualToken}
						onChange={(e) => setManualToken(e.target.value)}
						placeholder="QR token..."
						className="border-white/20 bg-white/10 text-white placeholder:text-white/30"
						onKeyDown={(e) => e.key === "Enter" && handleManualSubmit()}
					/>
					<Button
						onClick={handleManualSubmit}
						disabled={!manualToken.trim()}
						className="bg-white text-[#214e51] hover:bg-white/90"
					>
						OK
					</Button>
				</div>
			</div>

			<Button
				onClick={onCancel}
				variant="outline"
				className="w-full border-white/20 bg-transparent text-white hover:bg-white/10"
			>
				Annuleren
			</Button>
		</div>
	);
}
