<script lang="ts">
	import { onMount } from "svelte";
	import {
		clearDeviceSession,
		loadDeviceSession,
		setDeviceSessionId,
	} from "../../../api/session";
	import { loadStore } from "../../../platform/store/index";
	import type { OrderCommand } from "../../../sync/order-types";
	import {
		getMapCamera,
		getMapPickState,
		getMapPrimitives,
		type MapCameraSnapshot,
		type MapPickStateSnapshot,
		type MapPrimitiveSnapshot,
	} from "../../../lib/debug-surface.svelte";

	interface DebugSnapshot {
		publicKey: number[];
		deviceSessionId: string | null;
	}

	interface DebugSurface {
		ready: true;
		loadSession(): Promise<DebugSnapshot>;
		clearSession(): Promise<void>;
		signWithDevice(message: number[]): Promise<number[]>;
		setDeviceSessionId(id: string): Promise<void>;
		verifyWithStoredPublicKey(
			message: number[],
			signature: number[],
		): Promise<boolean>;
		seedOrderDraft(
			gameId: string,
			commands: OrderCommand[],
		): Promise<void>;
		clearOrderDraft(gameId: string): Promise<void>;
		getMapPrimitives(): readonly MapPrimitiveSnapshot[];
		getMapPickState(): MapPickStateSnapshot;
		getMapCamera(): MapCameraSnapshot | null;
	}

	type DebugWindow = typeof globalThis & { __galaxyDebug?: DebugSurface };

	let ready = $state(false);

	function describe(err: unknown): string {
		if (err instanceof Error) {
			return `${err.name}: ${err.message}`;
		}
		return String(err);
	}

	onMount(async () => {
		if (!import.meta.env.DEV) {
			return;
		}
		const { keyStore, cache } = await loadStore();
		const surface: DebugSurface = {
			ready: true,
			async loadSession() {
				try {
					const session = await loadDeviceSession(keyStore, cache);
					return {
						publicKey: Array.from(session.keypair.publicKey),
						deviceSessionId: session.deviceSessionId,
					};
				} catch (err) {
					throw new Error(`loadSession: ${describe(err)}`);
				}
			},
			async clearSession() {
				try {
					await clearDeviceSession(keyStore, cache);
				} catch (err) {
					throw new Error(`clearSession: ${describe(err)}`);
				}
			},
			async signWithDevice(message: number[]) {
				try {
					const session = await loadDeviceSession(keyStore, cache);
					const sig = await session.keypair.sign(new Uint8Array(message));
					return Array.from(sig);
				} catch (err) {
					throw new Error(`signWithDevice: ${describe(err)}`);
				}
			},
			async setDeviceSessionId(id: string) {
				try {
					await setDeviceSessionId(cache, id);
				} catch (err) {
					throw new Error(`setDeviceSessionId: ${describe(err)}`);
				}
			},
			async verifyWithStoredPublicKey(message, signature) {
				try {
					const session = await loadDeviceSession(keyStore, cache);
					const importedPublic = await crypto.subtle.importKey(
						"raw",
						session.keypair.publicKey as BufferSource,
						{ name: "Ed25519" },
						false,
						["verify"],
					);
					return await crypto.subtle.verify(
						{ name: "Ed25519" },
						importedPublic,
						new Uint8Array(signature) as BufferSource,
						new Uint8Array(message) as BufferSource,
					);
				} catch (err) {
					throw new Error(`verifyWithStoredPublicKey: ${describe(err)}`);
				}
			},
			async seedOrderDraft(gameId, commands) {
				try {
					await cache.put("order-drafts", `${gameId}/draft`, commands);
				} catch (err) {
					throw new Error(`seedOrderDraft: ${describe(err)}`);
				}
			},
			async clearOrderDraft(gameId) {
				try {
					await cache.delete("order-drafts", `${gameId}/draft`);
				} catch (err) {
					throw new Error(`clearOrderDraft: ${describe(err)}`);
				}
			},
			getMapPrimitives() {
				return getMapPrimitives();
			},
			getMapPickState() {
				return getMapPickState();
			},
			getMapCamera() {
				return getMapCamera();
			},
		};
		(window as DebugWindow).__galaxyDebug = surface;
		ready = true;
	});
</script>

<main>
	<h1>store debug</h1>
	{#if ready}
		<p data-testid="debug-store-ready">debug store ready</p>
	{:else}
		<p>booting…</p>
	{/if}
</main>

<style>
	main {
		padding: 2rem;
		font-family: system-ui, sans-serif;
	}
</style>
