// F8-10 end-to-end coverage for the planets table → map navigation.
// Boots an authenticated session, mocks the gateway with a small
// planets-only report, navigates to `table → planets`, clicks the
// first row, and asserts the active view switches to the map (which
// also implicitly proves that the `SelectionStore.focus` → map mount
// hand-off lands inside the live shell). Ship-groups and fleets are
// covered by their vitest specs — one e2e is enough to smoke the
// composed flow.

import { fromJson, type JsonValue } from "@bufbuild/protobuf";
import { expect, test, type Page } from "@playwright/test";

import { ExecuteCommandRequestSchema } from "../../src/proto/edge/v1/edge_gateway_pb";
import { forgeExecuteCommandResponseJson } from "./fixtures/sign-response";
import {
	buildMyGamesListPayload,
	type GameFixture,
} from "./fixtures/lobby-fbs";
import { buildReportPayload } from "./fixtures/report-fbs";

const SESSION_ID = "f8-10-tables-session";
const GAME_ID = "f8101010-0000-4000-8000-101010101010";

async function mockGateway(page: Page): Promise<void> {
	const game: GameFixture = {
		gameId: GAME_ID,
		gameName: "F8-10 Game",
		gameType: "private",
		status: "running",
		ownerUserId: "user-1",
		minPlayers: 2,
		maxPlayers: 8,
		enrollmentEndsAtMs: BigInt(Date.now() + 86_400_000),
		createdAtMs: BigInt(Date.now() - 86_400_000),
		updatedAtMs: BigInt(Date.now()),
		currentTurn: 1,
	};

	await page.route(
		"**/edge.v1.Gateway/ExecuteCommand",
		async (route) => {
			const reqText = route.request().postData();
			if (reqText === null) {
				await route.fulfill({ status: 400 });
				return;
			}
			const req = fromJson(
				ExecuteCommandRequestSchema,
				JSON.parse(reqText) as JsonValue,
			);

			let payload: Uint8Array;
			switch (req.messageType) {
				case "lobby.my.games.list":
					payload = buildMyGamesListPayload([game]);
					break;
				case "user.games.report":
					payload = buildReportPayload({
						turn: 1,
						mapWidth: 4000,
						mapHeight: 4000,
						localPlanets: [
							{ number: 1, name: "Home", x: 1000, y: 1000 },
						],
						otherPlanets: [
							{
								number: 2,
								name: "Frontier",
								x: 2000,
								y: 1500,
								owner: "Federation",
							},
						],
						uninhabitedPlanets: [
							{ number: 3, name: "Rock", x: 1500, y: 2200 },
						],
					});
					break;
				default:
					payload = new Uint8Array();
			}

			const body = await forgeExecuteCommandResponseJson({
				requestId: req.requestId,
				timestampMs: BigInt(Date.now()),
				resultCode: "ok",
				payloadBytes: payload,
			});
			await route.fulfill({
				status: 200,
				contentType: "application/json",
				body,
			});
		},
	);

	// Hold SubscribeEvents open — mirrors the pattern in other e2e
	// specs to avoid the revocation watcher signing the session out.
	await page.route(
		"**/edge.v1.Gateway/SubscribeEvents",
		async () => {
			await new Promise<void>(() => {});
		},
	);
}

async function bootSession(page: Page): Promise<void> {
	await page.goto("/__debug/store");
	await expect(page.getByTestId("debug-store-ready")).toBeVisible();
	await page.waitForFunction(() => window.__galaxyDebug?.ready === true);
	await page.evaluate(() => window.__galaxyDebug!.clearSession());
	await page.evaluate(
		(id) => window.__galaxyDebug!.setDeviceSessionId(id),
		SESSION_ID,
	);
}

test("clicking a row in the planets table opens the map", async ({ page }) => {
	await mockGateway(page);
	await bootSession(page);
	await page.goto("/");
	await page.waitForFunction(() => window.__galaxyNav !== undefined);
	await page.evaluate(
		(id) =>
			window.__galaxyNav!.enterGame(id, "table", {
				tableEntity: "planets",
			}),
		GAME_ID,
	);

	const table = page.getByTestId("planets-table");
	await expect(table).toBeVisible();
	const rows = page.getByTestId("planets-row");
	await expect(rows).toHaveCount(3);

	// Click the foreign planet — the data-* stamps let the spec assert
	// against a deterministic row regardless of default sort.
	await page
		.locator('[data-testid="planets-row"][data-number="2"]')
		.click();

	await expect(page.getByTestId("active-view-map")).toBeVisible();
});
