// Phase 12 end-to-end coverage for the order composer skeleton. The
// shell makes no gateway calls in this spec — the boot flow seeds an
// authenticated session and a draft directly through `/__debug/store`,
// then navigates into `/games/<id>/map` and exercises the order tab.
//
// Persistence is covered by reloading the page mid-spec: the
// `OrderDraftStore` re-reads the same cache row on the next mount,
// so the rendered list survives the round-trip.

import { expect, test, type Page } from "@playwright/test";

// `window.__galaxyDebug` is owned by `routes/__debug/store/+page.svelte`
// and typed by `tests/e2e/storage-keypair-persistence.spec.ts`. The
// merged global declaration covers every helper this spec calls.

const SESSION_ID = "phase-12-order-session";
const GAME_ID = "test-order";

const SEED = [
	{ kind: "placeholder" as const, id: "cmd-a", label: "first command" },
	{ kind: "placeholder" as const, id: "cmd-b", label: "second command" },
	{ kind: "placeholder" as const, id: "cmd-c", label: "third command" },
];

async function bootDebug(page: Page): Promise<void> {
	await page.goto("/__debug/store");
	await expect(page.getByTestId("debug-store-ready")).toBeVisible();
	await page.waitForFunction(() => window.__galaxyDebug?.ready === true);
}

async function seedShell(page: Page): Promise<void> {
	await bootDebug(page);
	await page.evaluate(() => window.__galaxyDebug!.clearSession());
	await page.evaluate(
		(id) => window.__galaxyDebug!.setDeviceSessionId(id),
		SESSION_ID,
	);
	await page.evaluate(
		({ gameId, commands }) =>
			window.__galaxyDebug!.clearOrderDraft(gameId).then(() =>
				window.__galaxyDebug!.seedOrderDraft(gameId, commands),
			),
		{ gameId: GAME_ID, commands: SEED },
	);
}

async function openOrderTool(page: Page, isMobile: boolean): Promise<void> {
	if (isMobile) {
		await page.getByTestId("bottom-tab-order").click();
	} else {
		await page.getByTestId("sidebar-tab-order").click();
	}
	await expect(page.getByTestId("sidebar-tool-order")).toBeVisible();
}

async function expectSeededRows(page: Page): Promise<void> {
	const list = page.getByTestId("order-list");
	await expect(list).toBeVisible();
	for (let i = 0; i < SEED.length; i++) {
		const row = page.getByTestId(`order-command-${i}`);
		await expect(row).toBeVisible();
		await expect(row.getByTestId(`order-command-label-${i}`)).toHaveText(
			SEED[i]!.label,
		);
	}
	await expect(page.getByTestId("order-empty")).toHaveCount(0);
}

test("seeded draft renders on the order tab and survives a reload", async ({
	page,
}, testInfo) => {
	const isMobile = testInfo.project.name.startsWith("chromium-mobile");
	await seedShell(page);
	await page.goto(`/games/${GAME_ID}/map`);
	await expect(page.getByTestId("game-shell")).toBeVisible();
	await expect(page.getByTestId("active-view-map")).toBeVisible();

	await openOrderTool(page, isMobile);
	await expectSeededRows(page);

	await page.reload();
	await expect(page.getByTestId("game-shell")).toBeVisible();
	await openOrderTool(page, isMobile);
	await expectSeededRows(page);
});

test("removing a command from the order tab persists the removal", async ({
	page,
}, testInfo) => {
	const isMobile = testInfo.project.name.startsWith("chromium-mobile");
	await seedShell(page);
	await page.goto(`/games/${GAME_ID}/map`);
	await expect(page.getByTestId("game-shell")).toBeVisible();
	await openOrderTool(page, isMobile);

	await expect(page.getByTestId("order-command-1")).toBeVisible();
	await page.getByTestId("order-command-delete-1").click();
	// The remaining two commands shift up by one slot.
	await expect(page.getByTestId("order-command-label-0")).toHaveText(
		SEED[0]!.label,
	);
	await expect(page.getByTestId("order-command-label-1")).toHaveText(
		SEED[2]!.label,
	);
	await expect(page.getByTestId("order-command-2")).toHaveCount(0);

	await page.reload();
	await expect(page.getByTestId("game-shell")).toBeVisible();
	await openOrderTool(page, isMobile);
	await expect(page.getByTestId("order-command-label-0")).toHaveText(
		SEED[0]!.label,
	);
	await expect(page.getByTestId("order-command-label-1")).toHaveText(
		SEED[2]!.label,
	);
	await expect(page.getByTestId("order-command-2")).toHaveCount(0);
});

test("empty draft renders the empty-state copy", async ({
	page,
}, testInfo) => {
	const isMobile = testInfo.project.name.startsWith("chromium-mobile");
	await bootDebug(page);
	await page.evaluate(() => window.__galaxyDebug!.clearSession());
	await page.evaluate(
		(id) => window.__galaxyDebug!.setDeviceSessionId(id),
		SESSION_ID,
	);
	await page.evaluate(
		(gameId) => window.__galaxyDebug!.clearOrderDraft(gameId),
		GAME_ID,
	);

	await page.goto(`/games/${GAME_ID}/map`);
	await expect(page.getByTestId("game-shell")).toBeVisible();
	await openOrderTool(page, isMobile);

	await expect(page.getByTestId("order-empty")).toBeVisible();
	await expect(page.getByTestId("order-list")).toHaveCount(0);
});
