<script lang="ts">
	import * as Dialog from '$lib/components/ui/dialog';
	import { Button } from '$lib/components/ui/button';
	import { Label } from '$lib/components/ui/label';
	import {
		addFlag,
		clearFlags,
		clearValidations,
		exportReviews,
		FLAG_REASONS,
		KNOWN_MINOR_ISSUES,
		loadFlags,
		loadValidations,
		type FlagReason
	} from '$lib/eval';
	import ArrowSquareOutIcon from 'phosphor-svelte/lib/ArrowSquareOutIcon';
	import ClipboardIcon from 'phosphor-svelte/lib/ClipboardIcon';
	import TrashIcon from 'phosphor-svelte/lib/TrashIcon';
	import { toast } from 'svelte-sonner';
	import { untrack } from 'svelte';

	interface Props {
		open?: boolean;
		matchId: number;
		mapName: string;
		round: number;
		queueLength: number;
		onChange?: () => void;
	}
	let { open = $bindable(false), matchId, mapName, round, queueLength, onChange }: Props = $props();

	let reason = $state<FlagReason | null>(null);
	let note = $state('');
	// Bumped to refresh the counts when the user copies/clears or saves a flag.
	let storeBump = $state(0);

	// Watch only `open`; everything inside is untracked so writes (especially
	// `storeBump++` which is a read+write) don't make the effect re-trigger
	// itself into an infinite loop.
	$effect(() => {
		const isOpen = open;
		untrack(() => {
			if (!isOpen) {
				reason = null;
				note = '';
			} else {
				storeBump++;
			}
		});
	});

	const flagsCount = $derived.by(() => {
		void storeBump;
		return loadFlags().length;
	});
	const validationsCount = $derived.by(() => {
		void storeBump;
		return loadValidations().length;
	});

	function save() {
		if (!reason) return;
		const trimmed = note.trim();
		addFlag({ matchId, mapName, round, reason, note: trimmed || undefined });
		const label = FLAG_REASONS.find((r) => r.id === reason)?.label ?? 'Flagged';
		toast.success(`Flagged: ${label}`, {
			description: `match ${matchId} · ${mapName} · round ${round}`
		});
		onChange?.();
		open = false;
	}

	async function copyAll() {
		const data = exportReviews(queueLength);
		try {
			await navigator.clipboard.writeText(JSON.stringify(data, null, 2));
			toast.success('Review data copied to clipboard', {
				description: `${data.flags.length} flags · ${data.validations.length} validations`
			});
		} catch {
			toast.error('Could not copy to clipboard');
		}
	}

	function clearAll() {
		clearFlags();
		clearValidations();
		storeBump++;
		onChange?.();
		toast.success('Cleared local review data');
	}
</script>

<Dialog.Root bind:open>
	<Dialog.Content
		class="flex max-h-[min(80vh,40rem)] w-full max-w-xl flex-col gap-3 overflow-hidden p-0 sm:max-w-xl"
	>
		<Dialog.Header class="border-b px-4 pt-4 pb-3">
			<Dialog.Title>Flag this candidate</Dialog.Title>
			<Dialog.Description>
				match {matchId} · {mapName} · round {round}. Pick a reason and (optionally) leave a note.
			</Dialog.Description>
		</Dialog.Header>

		<div class="flex min-h-0 flex-col gap-3 overflow-y-auto px-4">
			<div class="grid gap-1.5">
				{#each FLAG_REASONS as r (r.id)}
					<button
						type="button"
						data-active={reason === r.id || undefined}
						class="flex flex-col items-start gap-0.5 rounded-md border border-border px-2.5 py-1.5 text-left text-xs transition hover:bg-muted/50 data-active:border-amber-500 data-active:bg-amber-500/10"
						onclick={() => (reason = r.id)}
					>
						<span class="flex items-center gap-2">
							<span class="font-medium text-foreground">{r.label}</span>
							<span
								data-severity={r.severity}
								class="rounded-sm border px-1 py-0 text-[9px] font-semibold tracking-wider text-muted-foreground/80 uppercase data-[severity=major]:border-rose-500/30 data-[severity=major]:text-rose-600 dark:data-[severity=major]:text-rose-400"
								>{r.severity}</span
							>
						</span>
						<span class="text-[11px] leading-snug text-muted-foreground">{r.description}</span>
						{#if r.examples?.length}
							<span class="mt-1 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-[10px]">
								<span class="tracking-wider text-muted-foreground/70 uppercase">Examples:</span>
								{#each r.examples as href, i (href)}
									<a
										{href}
										target="_blank"
										rel="noreferrer noopener"
										onclick={(e) => e.stopPropagation()}
										class="inline-flex items-center gap-0.5 text-muted-foreground underline-offset-2 hover:text-foreground hover:underline"
									>
										#{i + 1}
										<ArrowSquareOutIcon size={10} weight="bold" />
									</a>
								{/each}
							</span>
						{/if}
					</button>
				{/each}
			</div>

			<div class="grid gap-1.5">
				<Label for="flag-note" class="text-xs">Notes (optional)</Label>
				<textarea
					id="flag-note"
					bind:value={note}
					placeholder="e.g. player 4 spawn position is at mid instead of T spawn from t=0"
					rows="3"
					class="w-full resize-y rounded-md border border-input bg-input/20 px-2 py-1.5 text-xs outline-none focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/30 dark:bg-input/30"
				></textarea>
			</div>

			{#each KNOWN_MINOR_ISSUES as k (k.label)}
				<div class="rounded-md border border-dashed border-muted-foreground/20 p-2.5 text-[11px]">
					<div
						class="mb-0.5 text-[10px] font-semibold tracking-wider text-muted-foreground/80 uppercase"
					>
						Don't flag — known minor
					</div>
					<div class="font-medium text-foreground">{k.label}</div>
					<div class="mt-0.5 leading-snug text-muted-foreground">{k.description}</div>
					{#if k.examples?.length}
						<div class="mt-1 flex flex-wrap gap-2 text-[10px]">
							{#each k.examples as href, i (href)}
								<a
									{href}
									target="_blank"
									rel="noreferrer noopener"
									class="inline-flex items-center gap-0.5 text-muted-foreground underline-offset-2 hover:text-foreground hover:underline"
								>
									#{i + 1}
									<ArrowSquareOutIcon size={10} weight="bold" />
								</a>
							{/each}
						</div>
					{/if}
				</div>
			{/each}

			<div class="rounded-md border bg-muted/30 px-2.5 py-2 text-[11px]">
				<div class="flex items-center justify-between gap-2">
					<div>
						<div class="font-medium text-foreground">Local review data</div>
						<div class="mt-0.5 text-[10px] text-muted-foreground">
							<span class="tabular-nums">{flagsCount}</span> flags ·
							<span class="tabular-nums">{validationsCount}</span> validations · stored in
							<code class="font-mono">localStorage</code> (persists across sessions)
						</div>
					</div>
					<div class="flex shrink-0 items-center gap-1">
						<Button variant="outline" size="sm" onclick={copyAll}>
							<ClipboardIcon size={12} weight="duotone" /> Copy
						</Button>
						<Button
							variant="ghost"
							size="icon-sm"
							onclick={clearAll}
							aria-label="Clear local review data"
						>
							<TrashIcon size={12} weight="duotone" />
						</Button>
					</div>
				</div>
			</div>
		</div>

		<Dialog.Footer class="border-t px-4 pt-3 pb-4">
			<Button variant="ghost" size="sm" onclick={() => (open = false)}>Cancel</Button>
			<Button size="sm" onclick={save} disabled={!reason}>Save flag</Button>
		</Dialog.Footer>
	</Dialog.Content>
</Dialog.Root>
