<script lang="ts">
	import { goto } from "$app/navigation";
	import { onMount } from "svelte";

	import { createEdgeGatewayClient } from "../../../api/connect";
	import { GalaxyClient } from "../../../api/galaxy-client";
	import { LobbyError, createGame } from "../../../api/lobby";
	import { GATEWAY_BASE_URL, GATEWAY_RESPONSE_PUBLIC_KEY } from "$lib/env";
	import { i18n, type TranslationKey } from "$lib/i18n/index.svelte";
	import { loadCore } from "../../../platform/core/index";
	import { session } from "$lib/session-store.svelte";

	const DEFAULT_MIN_PLAYERS = 2;
	const DEFAULT_MAX_PLAYERS = 8;
	const DEFAULT_START_GAP_HOURS = 24;
	const DEFAULT_START_GAP_PLAYERS = 2;
	const DEFAULT_TARGET_ENGINE_VERSION = "v1";

	let gameName = $state("");
	let description = $state("");
	let turnSchedule = $state("0 0 * * *");
	let enrollmentEndsAt = $state("");

	let minPlayers = $state(DEFAULT_MIN_PLAYERS);
	let maxPlayers = $state(DEFAULT_MAX_PLAYERS);
	let startGapHours = $state(DEFAULT_START_GAP_HOURS);
	let startGapPlayers = $state(DEFAULT_START_GAP_PLAYERS);
	let targetEngineVersion = $state(DEFAULT_TARGET_ENGINE_VERSION);

	let formError: string | null = $state(null);
	let configError: string | null = $state(null);
	let submitting = $state(false);

	let client: GalaxyClient | null = null;

	async function sha256(payload: Uint8Array): Promise<Uint8Array> {
		const digest = await crypto.subtle.digest("SHA-256", payload as BufferSource);
		return new Uint8Array(digest);
	}

	function describeLobbyError(err: unknown): string {
		if (err instanceof LobbyError) {
			const key = `lobby.error.${err.code}` as TranslationKey;
			const translated = i18n.t(key);
			if (translated !== key) {
				return translated;
			}
			return i18n.t("lobby.error.unknown", { message: err.message });
		}
		return err instanceof Error ? err.message : "request failed";
	}

	function cancel(): void {
		goto("/lobby");
	}

	async function submit(): Promise<void> {
		formError = null;
		const trimmedName = gameName.trim();
		const trimmedSchedule = turnSchedule.trim();
		const trimmedEnrollment = enrollmentEndsAt.trim();
		if (trimmedName === "") {
			formError = i18n.t("lobby.create.game_name_required");
			return;
		}
		if (trimmedSchedule === "") {
			formError = i18n.t("lobby.create.turn_schedule_required");
			return;
		}
		if (trimmedEnrollment === "") {
			formError = i18n.t("lobby.create.enrollment_ends_at_required");
			return;
		}
		const enrollmentDate = new Date(trimmedEnrollment);
		if (Number.isNaN(enrollmentDate.getTime())) {
			formError = i18n.t("lobby.create.enrollment_ends_at_required");
			return;
		}
		if (client === null) {
			formError = configError ?? "client not ready";
			return;
		}
		submitting = true;
		try {
			await createGame(client, {
				gameName: trimmedName,
				description: description.trim(),
				minPlayers,
				maxPlayers,
				startGapHours,
				startGapPlayers,
				enrollmentEndsAt: enrollmentDate,
				turnSchedule: trimmedSchedule,
				targetEngineVersion: targetEngineVersion.trim() || DEFAULT_TARGET_ENGINE_VERSION,
			});
			goto("/lobby");
		} catch (err) {
			formError = describeLobbyError(err);
		} finally {
			submitting = false;
		}
	}

	onMount(async () => {
		if (
			session.keypair === null ||
			session.deviceSessionId === null ||
			GATEWAY_RESPONSE_PUBLIC_KEY.length === 0
		) {
			if (GATEWAY_RESPONSE_PUBLIC_KEY.length === 0) {
				configError = "VITE_GATEWAY_RESPONSE_PUBLIC_KEY is not configured";
			}
			return;
		}
		const keypair = session.keypair;
		const core = await loadCore();
		client = new GalaxyClient({
			core,
			edge: createEdgeGatewayClient(GATEWAY_BASE_URL),
			signer: (canonical) => keypair.sign(canonical),
			sha256,
			deviceSessionId: session.deviceSessionId,
			gatewayResponsePublicKey: GATEWAY_RESPONSE_PUBLIC_KEY,
		});
	});
</script>

<main>
	<h1>{i18n.t("lobby.create.title")}</h1>
	{#if configError !== null}
		<p role="alert" data-testid="lobby-create-config-error">{configError}</p>
	{/if}
	<form
		onsubmit={(event) => {
			event.preventDefault();
			submit();
		}}
		data-testid="lobby-create-form"
	>
		<label>
			{i18n.t("lobby.create.game_name_label")}
			<input
				type="text"
				bind:value={gameName}
				data-testid="lobby-create-game-name"
				autocomplete="off"
			/>
		</label>
		<label>
			{i18n.t("lobby.create.description_label")}
			<textarea
				bind:value={description}
				data-testid="lobby-create-description"
				rows="3"
			></textarea>
		</label>
		<label>
			{i18n.t("lobby.create.turn_schedule_label")}
			<input
				type="text"
				bind:value={turnSchedule}
				data-testid="lobby-create-turn-schedule"
				autocomplete="off"
			/>
			<small>{i18n.t("lobby.create.turn_schedule_hint")}</small>
		</label>
		<label>
			{i18n.t("lobby.create.enrollment_ends_at_label")}
			<input
				type="datetime-local"
				bind:value={enrollmentEndsAt}
				data-testid="lobby-create-enrollment-ends-at"
			/>
		</label>
		<details data-testid="lobby-create-advanced">
			<summary>{i18n.t("lobby.create.advanced")}</summary>
			<label>
				{i18n.t("lobby.create.min_players_label")}
				<input
					type="number"
					min="1"
					bind:value={minPlayers}
					data-testid="lobby-create-min-players"
				/>
			</label>
			<label>
				{i18n.t("lobby.create.max_players_label")}
				<input
					type="number"
					min="1"
					bind:value={maxPlayers}
					data-testid="lobby-create-max-players"
				/>
			</label>
			<label>
				{i18n.t("lobby.create.start_gap_hours_label")}
				<input
					type="number"
					min="0"
					bind:value={startGapHours}
					data-testid="lobby-create-start-gap-hours"
				/>
			</label>
			<label>
				{i18n.t("lobby.create.start_gap_players_label")}
				<input
					type="number"
					min="0"
					bind:value={startGapPlayers}
					data-testid="lobby-create-start-gap-players"
				/>
			</label>
			<label>
				{i18n.t("lobby.create.target_engine_version_label")}
				<input
					type="text"
					bind:value={targetEngineVersion}
					data-testid="lobby-create-target-engine-version"
					autocomplete="off"
				/>
			</label>
		</details>
		{#if formError !== null}
			<p role="alert" data-testid="lobby-create-error">{formError}</p>
		{/if}
		<div class="actions">
			<button type="submit" disabled={submitting} data-testid="lobby-create-submit">
				{submitting ? i18n.t("lobby.create.submitting") : i18n.t("lobby.create.submit")}
			</button>
			<button type="button" onclick={cancel} data-testid="lobby-create-cancel">
				{i18n.t("lobby.create.cancel")}
			</button>
		</div>
	</form>
</main>

<style>
	main {
		padding: 1.5rem 1rem;
		max-width: 32rem;
		margin: 0 auto;
		font-family: system-ui, sans-serif;
	}

	form {
		display: flex;
		flex-direction: column;
		gap: 0.75rem;
	}

	label {
		display: flex;
		flex-direction: column;
		gap: 0.25rem;
	}

	input[type="text"],
	input[type="number"],
	input[type="datetime-local"],
	textarea {
		font-size: 1rem;
		padding: 0.4rem 0.5rem;
	}

	details {
		border: 1px solid #ddd;
		border-radius: 0.4rem;
		padding: 0.5rem 0.75rem;
		display: flex;
		flex-direction: column;
		gap: 0.5rem;
	}

	details > label {
		margin-top: 0.5rem;
	}

	details summary {
		cursor: pointer;
		font-weight: 600;
	}

	.actions {
		display: flex;
		gap: 0.5rem;
		margin-top: 0.5rem;
	}

	small {
		color: #666;
	}
</style>
