<script lang="ts">
	import {
		Shield,
		ShieldAlert,
		ShieldCheck,
		Loader2,
		X,
		Download,
		ExternalLink,
		Lock,
		Users,
		CheckCircle2,
		Key,
		Copy,
		Check,
	} from 'lucide-svelte';
	import { verifyAsset } from '$lib/verifier';
	import { backgroundVerify } from '$lib/verificationStore';
	import type { Contributor, SourceSecurity, VerificationStep } from '$lib/types';

	interface Props {
		assetName: string;
		assetUrl: string;
		expectedHash: string;
		contributors?: Contributor[];
		security?: SourceSecurity;
		onClose: () => void;
	}

	let { assetName, assetUrl, expectedHash, contributors, security, onClose }: Props = $props();
	let dontShowAgain = $state(false);
	let selectedContributor = $state<Contributor | null>(null);
	let copiedKeyIndex = $state<number | null>(null);

	let status = $state<'idle' | 'downloading' | 'verifying' | 'success' | 'error'>('idle');
	let errorMessage = $state('');
	let progress = $state(0);
	let steps = $state<VerificationStep[]>([]);

	function copyKey(key: string, index: number) {
		navigator.clipboard.writeText(key);
		copiedKeyIndex = index;
		setTimeout(() => (copiedKeyIndex = null), 2000);
	}

	function savePreference(accepted: boolean) {
		if (dontShowAgain) {
			localStorage.setItem('verification_preference', accepted ? 'accept' : 'decline');
		}
	}

	async function startVerification() {
		savePreference(true);

		// If "Don't show again" is checked and accepted, trigger background verification and close modal
		if (dontShowAgain) {
			backgroundVerify(assetName, assetUrl, expectedHash);
			onClose();
			return;
		}

		status = 'downloading';
		try {
			const response = await fetch(assetUrl);
			if (!response.ok) throw new Error('Download failed');

			const contentLength = response.headers.get('content-length');
			const total = contentLength ? parseInt(contentLength, 10) : 0;
			const contentType = response.headers.get('content-type') || 'application/octet-stream';

			const reader = response.body?.getReader();
			if (!reader) throw new Error('Failed to read response body');

			let receivedLength = 0;
			const chunks = [];

			while (true) {
				const { done, value } = await reader.read();
				if (done) break;
				chunks.push(value);
				receivedLength += value.length;
				if (total) progress = Math.round((receivedLength / total) * 100);
			}

			const data = new Uint8Array(receivedLength);
			let position = 0;
			for (const chunk of chunks) {
				data.set(chunk, position);
				position += chunk.length;
			}

			status = 'verifying';
			const result = await verifyAsset(data.buffer, expectedHash);
			steps = result.steps;

			if (result.valid) {
				status = 'success';
				// Trigger actual download from the blob
				const blob = new Blob([data], { type: contentType });
				const url = window.URL.createObjectURL(blob);
				const a = document.createElement('a');
				a.href = url;
				a.download = assetName;
				document.body.appendChild(a);
				a.click();
				window.URL.revokeObjectURL(url);
				document.body.removeChild(a);
			} else {
				status = 'error';
				errorMessage = result.error || 'Verification failed';
			}
		} catch (e: any) {
			status = 'error';
			errorMessage = e.message;
		}
	}

	function skipVerification() {
		savePreference(false);
		const a = document.createElement('a');
		a.href = assetUrl;
		a.download = assetName;
		document.body.appendChild(a);
		a.click();
		document.body.removeChild(a);
		onClose();
	}
</script>

<div
	class="fixed inset-0 z-[100] flex items-center justify-center p-4 bg-background/80 backdrop-blur-sm"
>
	<div
		class="w-full max-w-md bg-card border border-border rounded-2xl shadow-2xl overflow-hidden animate-in fade-in zoom-in duration-200"
	>
		<div class="p-6">
			<div class="flex items-center justify-between mb-6">
				<div class="flex items-center gap-3">
					<div class="p-2 rounded-lg bg-primary/10 text-primary">
						<Shield class="w-6 h-6" />
					</div>
					<div>
						<h3 class="text-xl font-bold leading-none">Verify Download</h3>
						<a
							href="https://git.quad4.io/Quad4-Software/software-station/src/branch/master/software-verifier"
							target="_blank"
							class="text-[10px] text-muted-foreground hover:text-primary transition-colors flex items-center gap-1 mt-1"
						>
							Code <ExternalLink class="w-2.5 h-2.5" />
						</a>
					</div>
				</div>
				<button
					onclick={onClose}
					class="p-2 hover:bg-muted rounded-full transition-colors"
					aria-label="Close"
				>
					<X class="w-5 h-5" />
				</button>
			</div>

			<div class="space-y-4">
				<div class="bg-muted/30 rounded-xl p-4 border border-border/50">
					<p class="text-xs text-muted-foreground mb-2">Target Asset</p>
					<p class="text-sm font-bold truncate">{assetName}</p>

					{#if security}
						<div class="flex items-center gap-4 mt-3 pt-3 border-t border-border/50">
							<div class="flex items-center gap-1.5" title="TLS Certificate Validation">
								<Lock
									class="w-3.5 h-3.5 {security.tls_valid
										? 'text-green-700 dark:text-green-400'
										: 'text-destructive'}"
								/>
								<span class="text-[10px] font-bold uppercase tracking-tight">TLS</span>
							</div>
							<div class="flex-1 text-right">
								<span class="text-[10px] text-muted-foreground font-medium">{security.domain}</span>
							</div>
						</div>
					{/if}
				</div>

				{#if contributors && contributors.length > 0}
					<div class="bg-muted/30 rounded-xl p-4 border border-border/50">
						<div class="flex items-center justify-between mb-3">
							<div class="flex items-center gap-2">
								<Users class="w-4 h-4 text-primary" />
								<span class="text-xs font-bold uppercase tracking-wider">Contributors</span>
							</div>
							<span class="text-[10px] text-muted-foreground font-medium"
								>{contributors.length} Users</span
							>
						</div>
						<div class="flex flex-wrap gap-2">
							{#each contributors as contributor}
								<button
									onclick={() =>
										(selectedContributor =
											selectedContributor?.username === contributor.username ? null : contributor)}
									class="flex items-center gap-1.5 bg-background border {selectedContributor?.username ===
									contributor.username
										? 'border-primary shadow-sm'
										: 'border-border'} rounded-full pl-1 pr-2 py-1 transition-all hover:border-primary/50"
									title={contributor.username}
								>
									<img
										src={contributor.avatar_url}
										alt={contributor.username}
										class="w-4 h-4 rounded-full"
									/>
									<span class="text-[10px] font-medium max-w-[80px] truncate"
										>{contributor.username}</span
									>
									{#if contributor.gpg_keys && contributor.gpg_keys.length > 0}
										<Key class="w-2.5 h-2.5 text-orange-500" />
									{/if}
								</button>
							{/each}
						</div>

						{#if selectedContributor}
							<div
								class="mt-4 pt-4 border-t border-border/50 animate-in fade-in slide-in-from-top-1 duration-200"
							>
								<div class="flex items-center justify-between mb-2">
									<p class="text-[10px] font-bold uppercase tracking-widest text-muted-foreground">
										Public GPG Keys
									</p>
									<span
										class="text-[9px] px-1.5 py-0.5 rounded bg-orange-500/10 text-orange-700 dark:text-orange-400 font-bold"
										>{selectedContributor.gpg_keys?.length || 0} Keys</span
									>
								</div>

								{#if selectedContributor.gpg_keys && selectedContributor.gpg_keys.length > 0}
									<div class="space-y-2">
										{#each selectedContributor.gpg_keys as key, idx}
											<div class="group relative">
												<pre
													class="text-[8px] bg-zinc-950 text-zinc-400 p-2 rounded-lg overflow-x-auto font-mono leading-tight max-h-32 scrollbar-thin"><code
														>{key}</code
													></pre>
												<button
													onclick={() => copyKey(key, idx)}
													class="absolute top-2 right-2 p-1.5 bg-white/5 hover:bg-white/10 rounded-md transition-colors text-white/50 hover:text-white"
													title="Copy Public Key"
												>
													{#if copiedKeyIndex === idx}
														<Check class="w-3 h-3 text-green-500" />
													{:else}
														<Copy class="w-3 h-3" />
													{/if}
												</button>
											</div>
										{/each}
									</div>
								{:else}
									<p class="text-[10px] text-muted-foreground italic">
										No public GPG keys found for this user.
									</p>
								{/if}
							</div>
						{/if}
					</div>
				{/if}

				{#if status === 'idle'}
					<div class="flex flex-col gap-3 pt-2">
						<button
							onclick={startVerification}
							class="w-full py-3 px-4 bg-primary text-primary-foreground rounded-xl font-semibold hover:opacity-90 transition-opacity flex items-center justify-center gap-2 shadow-lg shadow-primary/20"
						>
							<ShieldCheck class="w-5 h-5" />
							Verify and Download
						</button>
						<button
							onclick={skipVerification}
							class="w-full py-3 px-4 bg-muted text-muted-foreground rounded-xl font-semibold hover:bg-muted/80 transition-colors flex items-center justify-center gap-2"
						>
							<Download class="w-5 h-5" />
							Download without verification
						</button>
					</div>

					<div class="flex items-center gap-2 mt-2">
						<label class="flex items-center gap-2 cursor-pointer group">
							<div class="relative flex items-center">
								<input type="checkbox" bind:checked={dontShowAgain} class="peer sr-only" />
								<div
									class="w-4 h-4 rounded border border-input bg-background peer-checked:bg-primary peer-checked:border-primary transition-all"
								></div>
								<svg
									class="absolute w-3 h-3 text-primary-foreground opacity-0 peer-checked:opacity-100 transition-opacity left-0"
									fill="none"
									viewBox="0 0 24 24"
									stroke="currentColor"
									stroke-width="4"
								>
									<path d="M5 13l4 4L19 7" />
								</svg>
							</div>
							<span
								class="text-[11px] text-muted-foreground group-hover:text-foreground transition-colors"
								>Remember this preference</span
							>
						</label>
					</div>
				{:else if status === 'downloading' || status === 'verifying'}
					<div
						class="py-8 bg-muted/20 rounded-xl border border-border/50 flex flex-col items-center justify-center gap-4"
					>
						<div class="relative w-16 h-16">
							<Loader2 class="w-16 h-16 text-primary animate-spin opacity-20" />
							<div class="absolute inset-0 flex items-center justify-center">
								{#if status === 'downloading'}
									<div class="text-sm font-bold text-primary">{progress}%</div>
								{:else}
									<Shield class="w-8 h-8 text-primary animate-pulse" />
								{/if}
							</div>
						</div>
						<div class="text-center">
							<p class="text-sm font-bold tracking-tight">
								{#if status === 'downloading'}
									Downloading asset...
								{:else}
									Running WASM verification...
								{/if}
							</p>
							<p class="text-[10px] text-muted-foreground mt-1">
								{status === 'downloading'
									? `Fetching raw binary from source${progress > 0 ? ` • ${progress}%` : ''}`
									: 'Computing SHA256 in sandbox'}
							</p>
						</div>
					</div>
				{:else if status === 'success'}
					<div class="space-y-4">
						<div
							class="py-8 bg-green-500/5 rounded-xl border border-green-500/20 flex flex-col items-center justify-center gap-4 text-green-700 dark:text-green-400"
						>
							<div class="p-4 rounded-full bg-green-500/10">
								<ShieldCheck class="w-12 h-12" />
							</div>
							<div class="text-center">
								<p class="font-bold text-lg leading-tight">Verification Successful!</p>
								<p class="text-xs text-muted-foreground mt-1">Binary integrity is guaranteed</p>
							</div>
						</div>

						{#if steps.length > 0}
							<div class="bg-muted/30 rounded-xl overflow-hidden border border-border/50">
								<div
									class="px-4 py-2 bg-muted/50 border-b border-border/50 flex items-center gap-2"
								>
									<CheckCircle2 class="w-3 h-3 text-green-700 dark:text-green-400" />
									<span class="text-[10px] font-bold uppercase tracking-wider"
										>Verification Audit</span
									>
								</div>
								<div class="p-3 space-y-3">
									{#each steps as step}
										<div class="flex gap-3">
											<div class="mt-0.5">
												{#if step.status === 'success'}
													<CheckCircle2 class="w-3 h-3 text-green-700 dark:text-green-400" />
												{:else if step.status === 'error'}
													<ShieldAlert class="w-3 h-3 text-destructive" />
												{:else}
													<Loader2 class="w-3 h-3 text-muted-foreground animate-spin" />
												{/if}
											</div>
											<div class="min-w-0">
												<p class="text-[11px] font-bold leading-none">{step.name}</p>
												<p class="text-[10px] text-muted-foreground mt-1 leading-normal">
													{step.details}
												</p>
											</div>
										</div>
									{/each}
								</div>
							</div>
						{/if}

						<button
							onclick={onClose}
							class="w-full py-3 px-4 bg-green-700 dark:bg-green-600 text-white rounded-xl font-semibold hover:opacity-90 transition-opacity flex items-center justify-center gap-2"
						>
							Start Using Software
						</button>
					</div>
				{:else if status === 'error'}
					<div class="space-y-4">
						<div
							class="py-8 bg-destructive/5 rounded-xl border border-destructive/20 flex flex-col items-center justify-center gap-4 text-destructive"
						>
							<div class="p-4 rounded-full bg-destructive/10">
								<ShieldAlert class="w-12 h-12" />
							</div>
							<div class="text-center px-4">
								<p class="font-bold text-lg leading-tight">Verification Failed</p>
								{#if errorMessage.includes('(')}
									<p class="text-sm font-bold mt-1">
										{errorMessage.split(' (')[0]}
									</p>
									<p class="text-[10px] text-muted-foreground mt-0.5 italic">
										({errorMessage.split(' (')[1]}
									</p>
								{:else}
									<p class="text-xs text-muted-foreground mt-1">{errorMessage}</p>
								{/if}
							</div>
						</div>

						{#if steps.length > 0}
							<div class="bg-muted/30 rounded-xl overflow-hidden border border-border/50">
								<div
									class="px-4 py-2 bg-muted/50 border-b border-border/50 flex items-center gap-2"
								>
									<ShieldAlert class="w-3 h-3 text-destructive" />
									<span class="text-[10px] font-bold uppercase tracking-wider text-destructive"
										>Failure Analysis</span
									>
								</div>
								<div class="p-3 space-y-3">
									{#each steps as step}
										<div class="flex gap-3">
											<div class="mt-0.5">
												{#if step.status === 'success'}
													<CheckCircle2 class="w-3 h-3 text-green-700 dark:text-green-400" />
												{:else if step.status === 'error'}
													<ShieldAlert class="w-3 h-3 text-destructive" />
												{:else}
													<Loader2 class="w-3 h-3 text-muted-foreground animate-spin" />
												{/if}
											</div>
											<div class="min-w-0">
												<p class="text-[11px] font-bold leading-none">{step.name}</p>
												<p class="text-[10px] text-muted-foreground mt-1 leading-normal">
													{step.details}
												</p>
											</div>
										</div>
									{/each}
								</div>
							</div>
						{/if}

						<div class="flex gap-3 pt-2">
							<button
								onclick={() => (status = 'idle')}
								class="flex-1 py-3 px-4 bg-muted text-muted-foreground rounded-xl font-semibold hover:bg-muted/80 transition-colors"
							>
								Try Again
							</button>
							<button
								onclick={skipVerification}
								class="flex-1 py-3 px-4 bg-destructive text-destructive-foreground rounded-xl font-semibold hover:opacity-90 transition-opacity"
							>
								Download Anyway
							</button>
						</div>
					</div>
				{/if}
			</div>
		</div>

		<div class="px-6 py-4 bg-muted/50 border-t border-border flex items-center justify-between">
			<div
				class="flex items-center gap-2 text-[10px] text-muted-foreground uppercase tracking-wider font-bold"
			>
				<span class="px-1.5 py-0.5 rounded bg-primary/10 text-primary border border-primary/20"
					>WASM</span
				>
				<span>Client-side security</span>
			</div>
			<p class="text-[10px] text-muted-foreground">Powered by Go</p>
		</div>
	</div>
</div>
