<script lang="ts">
	import { onMount, onDestroy } from 'svelte';

	interface Props {
		ondetect: (barcode: string) => void;
		onclose: () => void;
	}

	let { ondetect, onclose }: Props = $props();

	let videoEl = $state<HTMLVideoElement | null>(null);
	let error = $state<string | null>(null);
	let stream: MediaStream | null = null;
	let animFrame: number | null = null;
	let detector: InstanceType<typeof BarcodeDetector> | null = null;
	let detected = $state(false);

	onMount(async () => {
		// Use native BarcodeDetector if available, otherwise load polyfill (Safari, Firefox)
		let BarcodeDetectorImpl: typeof BarcodeDetector;
		if ('BarcodeDetector' in window) {
			BarcodeDetectorImpl = BarcodeDetector;
		} else {
			const { BarcodeDetector: Polyfill } = await import('barcode-detector/ponyfill');
			BarcodeDetectorImpl = Polyfill as unknown as typeof BarcodeDetector;
		}

		try {
			stream = await navigator.mediaDevices.getUserMedia({
				video: { facingMode: 'environment', width: { ideal: 1280 }, height: { ideal: 720 } }
			});
		} catch {
			error = 'Camera access denied. Please allow camera permission and try again.';
			return;
		}

		if (!videoEl) return;
		videoEl.srcObject = stream;
		await videoEl.play();

		detector = new BarcodeDetectorImpl({ formats: ['ean_13', 'ean_8', 'upc_a', 'upc_e', 'code_128', 'code_39', 'qr_code'] });
		scanLoop();
	});

	onDestroy(cleanup);

	function cleanup() {
		if (animFrame !== null) cancelAnimationFrame(animFrame);
		stream?.getTracks().forEach(t => t.stop());
	}

	async function scanLoop() {
		if (!videoEl || !detector || videoEl.readyState < 2) {
			animFrame = requestAnimationFrame(scanLoop);
			return;
		}

		try {
			const results = await detector.detect(videoEl);
			if (results.length > 0 && !detected) {
				detected = true;
				cleanup();
				ondetect(results[0].rawValue);
				return;
			}
		} catch {
			// frame not ready, keep scanning
		}

		animFrame = requestAnimationFrame(scanLoop);
	}
</script>

<!-- Full-screen scanner overlay -->
<div class="fixed inset-0 z-50 bg-black flex flex-col">
	<!-- Top bar -->
	<div class="flex items-center justify-between px-4 pt-[calc(1rem+var(--safe-top))] pb-4">
		<span class="text-sm font-medium text-white">Scan barcode</span>
		<button
			onclick={() => { cleanup(); onclose(); }}
			class="w-9 h-9 flex items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/20 transition-colors"
			aria-label="Close scanner"
		>
			<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
				<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
			</svg>
		</button>
	</div>

	{#if error}
		<div class="flex-1 flex items-center justify-center px-8 text-center">
			<div>
				<svg class="w-12 h-12 text-zinc-500 mx-auto mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
					<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M12 9v2m0 4h.01M5.07 19H19a2 2 0 001.75-2.97L13.75 4a2 2 0 00-3.5 0L3.25 16.03A2 2 0 005.07 19z" />
				</svg>
				<p class="text-white text-sm">{error}</p>
			</div>
		</div>
	{:else}
		<!-- Camera feed -->
		<div class="flex-1 relative overflow-hidden">
			<!-- svelte-ignore a11y_media_has_caption -->
			<video
				bind:this={videoEl}
				playsinline
				muted
				class="absolute inset-0 w-full h-full object-cover"
			></video>

			<!-- Dark overlay with cutout effect -->
			<div class="absolute inset-0 flex items-center justify-center">
				<div class="absolute inset-0 bg-black/50"></div>

				<!-- Scan window -->
				<div class="relative z-10 w-64 h-40">
					<!-- Clear the overlay in the scan area -->
					<div class="absolute inset-0 bg-transparent mix-blend-normal"></div>

					<!-- Corner brackets -->
					<div class="absolute top-0 left-0 w-6 h-6 border-t-2 border-l-2 border-green-400 rounded-tl"></div>
					<div class="absolute top-0 right-0 w-6 h-6 border-t-2 border-r-2 border-green-400 rounded-tr"></div>
					<div class="absolute bottom-0 left-0 w-6 h-6 border-b-2 border-l-2 border-green-400 rounded-bl"></div>
					<div class="absolute bottom-0 right-0 w-6 h-6 border-b-2 border-r-2 border-green-400 rounded-br"></div>

					<!-- Scanning line -->
					{#if !detected}
						<div class="absolute left-1 right-1 h-0.5 bg-green-400/80 rounded animate-scan"></div>
					{:else}
						<div class="absolute inset-0 bg-green-400/20 rounded flex items-center justify-center">
							<svg class="w-8 h-8 text-green-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
								<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M5 13l4 4L19 7" />
							</svg>
						</div>
					{/if}
				</div>
			</div>
		</div>

		<!-- Hint -->
		<div class="py-6 text-center pb-[calc(1.5rem+var(--safe-bottom))]">
			<p class="text-zinc-400 text-sm">Point the camera at a barcode</p>
		</div>
	{/if}
</div>

<style>
	@keyframes scan {
		0%, 100% { top: 8px; }
		50% { top: calc(100% - 8px); }
	}
	.animate-scan {
		animation: scan 1.8s ease-in-out infinite;
	}
</style>
