<script lang="ts">
	// Single-route screen dispatcher for the app-shell. There are no
	// per-screen routes: the visible screen is selected from in-memory
	// state (`session.status` for the auth gate, `appScreen.screen` for
	// the authenticated screen) rather than from the URL. The root
	// layout intercepts the `loading` and `unsupported` session states
	// before this component renders, so here `session.status` is either
	// `anonymous` (login) or `authenticated` (lobby / create / game).
	import { onMount } from "svelte";
	import { dev } from "$app/environment";
	import { session } from "$lib/session-store.svelte";
	import {
		appScreen,
		activeView,
		type AppScreen,
		type GameView,
		type GameViewState,
	} from "$lib/app-nav.svelte";
	import LoginScreen from "$lib/screens/login-screen.svelte";
	import LobbyScreen from "$lib/screens/lobby-screen.svelte";
	import LobbyCreateScreen from "$lib/screens/lobby-create-screen.svelte";
	import ProfileScreen from "$lib/screens/profile-screen.svelte";
	import GameShell from "$lib/game/game-shell.svelte";
	import GamesActivePastScreen from "$lib/screens/games-active-past-screen.svelte";
	import GamesRecruitmentScreen from "$lib/screens/games-recruitment-screen.svelte";
	import GamesInvitationsScreen from "$lib/screens/games-invitations-screen.svelte";
	import GamesPrivateGamesScreen from "$lib/screens/games-private-games-screen.svelte";
	import SyntheticReportsScreen from "$lib/screens/synthetic-reports-screen.svelte";
	import { pushState } from "$app/navigation";
	import { page } from "$app/state";

	// Dev-only navigation affordance for the Playwright e2e suite. The
	// single-URL app-shell has no per-screen / per-view routes, so a
	// spec can no longer drive the UI by `page.goto("/games/:id/:view")`.
	// Instead the suite seeds the session, loads `/` (which lands on the
	// authenticated lobby), then calls `window.__galaxyNav.enterGame(...)`
	// to switch the in-memory screen and view. Guarded by `dev` so it is
	// stripped from the production bundle — `import.meta.env.DEV` (and the
	// SvelteKit `dev` re-export) is statically `false` there, so the
	// whole `onMount` body tree-shakes away.
	type ViewParams = Omit<GameViewState, "view">;
	interface NavSurface {
		enterGame(gameId: string, view?: GameView, params?: ViewParams): void;
		select(view: GameView, params?: ViewParams): void;
		go(screen: AppScreen, opts?: { gameId?: string }): void;
	}
	type NavWindow = typeof globalThis & { __galaxyNav?: NavSurface };

	onMount(() => {
		if (!dev) return;
		(window as NavWindow).__galaxyNav = {
			enterGame(gameId, view = "map", params = {}): void {
				activeView.select(view, params);
				appScreen.go("game", { gameId });
			},
			select(view, params = {}): void {
				activeView.select(view, params);
			},
			go(screen, opts = {}): void {
				appScreen.go(screen, opts);
			},
		};
	});

	// Screen-level browser history (Back → lobby) without changing the URL.
	// On the first authenticated render, stamp a restored overlay (game /
	// lobby-create) on top of the load entry so Back falls through to lobby.
	let historyStamped = $state(false);
	$effect(() => {
		if (session.status === "authenticated" && !historyStamped) {
			historyStamped = true;
			if (appScreen.screen === "game" && appScreen.gameId !== null) {
				pushState("", { screen: "game", gameId: appScreen.gameId });
			} else if (appScreen.screen === "lobby-create") {
				pushState("", { screen: "lobby-create" });
			} else if (appScreen.screen === "profile") {
				pushState("", { screen: "profile" });
			}
		}
	});

	// Sync the store from history on Back/Forward (popstate updates
	// `page.state`). Skipped until the baseline is stamped so it never
	// clobbers the restored screen on first render.
	$effect(() => {
		if (!historyStamped) return;
		appScreen.syncFromHistory(page.state.screen, page.state.gameId ?? null);
	});
</script>

{#if session.status === "authenticated"}
	{#if appScreen.screen === "lobby-create"}
		<LobbyCreateScreen />
	{:else if appScreen.screen === "profile"}
		<ProfileScreen />
	{:else if appScreen.screen === "game" && appScreen.gameId !== null}
		<GameShell />
	{:else if appScreen.screen === "games-active-past"}
		<GamesActivePastScreen />
	{:else if appScreen.screen === "games-recruitment"}
		<GamesRecruitmentScreen />
	{:else if appScreen.screen === "games-invitations"}
		<GamesInvitationsScreen />
	{:else if appScreen.screen === "games-private-games"}
		<GamesPrivateGamesScreen />
	{:else if appScreen.screen === "synthetic-reports"}
		<SyntheticReportsScreen />
	{:else}
		<!--
		Default authenticated screen. Covers the historical `lobby`
		alias and any restored snapshot that lost its game id. The
		`LobbyScreen` resolver navigates to `games-recruitment` on
		mount; the shell then re-routes to a more appropriate
		sub-page if visibility rules allow.
		-->
		<LobbyScreen />
	{/if}
{:else}
	<LoginScreen />
{/if}
