// Pure-state coverage for the lobby `games` submenu visibility rules.
// The same helper drives the sidebar's auto-expanded sub-item and the
// bare-`lobby` resolver's redirect target; if they ever disagree the
// player lands on the wrong sub-page on entry.

import { describe, expect, test } from "vitest";

import {
	firstVisibleGamesScreen,
	visibleGamesSubScreens,
	type LobbyNavState,
} from "../src/lib/lobby-nav";

function state(overrides: Partial<LobbyNavState> = {}): LobbyNavState {
	return {
		hasMyGames: false,
		hasInvitations: false,
		isPaidOrDev: false,
		...overrides,
	};
}

describe("visibleGamesSubScreens", () => {
	test("free-tier player with nothing — only recruitment is visible", () => {
		expect(visibleGamesSubScreens(state())).toEqual(["games-recruitment"]);
	});

	test("player with games — active-past leads recruitment", () => {
		expect(visibleGamesSubScreens(state({ hasMyGames: true }))).toEqual([
			"games-active-past",
			"games-recruitment",
		]);
	});

	test("player with pending invites — invitations appears after recruitment", () => {
		expect(visibleGamesSubScreens(state({ hasInvitations: true }))).toEqual([
			"games-recruitment",
			"games-invitations",
		]);
	});

	test("paid / DEV tier — private-games tails the list", () => {
		expect(visibleGamesSubScreens(state({ isPaidOrDev: true }))).toEqual([
			"games-recruitment",
			"games-private-games",
		]);
	});

	test("all four flags on — full canonical order", () => {
		expect(
			visibleGamesSubScreens(
				state({
					hasMyGames: true,
					hasInvitations: true,
					isPaidOrDev: true,
				}),
			),
		).toEqual([
			"games-active-past",
			"games-recruitment",
			"games-invitations",
			"games-private-games",
		]);
	});

	test("recruitment is always present regardless of input", () => {
		const variants: LobbyNavState[] = [
			state(),
			state({ hasMyGames: true }),
			state({ hasInvitations: true }),
			state({ isPaidOrDev: true }),
			state({ hasMyGames: true, hasInvitations: true, isPaidOrDev: true }),
		];
		for (const v of variants) {
			expect(visibleGamesSubScreens(v)).toContain("games-recruitment");
		}
	});
});

describe("firstVisibleGamesScreen", () => {
	test("free-tier nothing → recruitment", () => {
		expect(firstVisibleGamesScreen(state())).toBe("games-recruitment");
	});

	test("player with games → active-past wins", () => {
		expect(firstVisibleGamesScreen(state({ hasMyGames: true }))).toBe(
			"games-active-past",
		);
	});

	test("invitee-only (no games yet) → recruitment still wins over invitations by canonical order", () => {
		// Pending invites do NOT promote `invitations` above `recruitment`;
		// the canonical order places `recruitment` second only to
		// `active-past`. This guards against accidentally re-ordering the
		// sub-items in a way that surprises invitee-only sessions.
		expect(firstVisibleGamesScreen(state({ hasInvitations: true }))).toBe(
			"games-recruitment",
		);
	});

	test("games + invites → active-past still wins", () => {
		expect(
			firstVisibleGamesScreen(
				state({ hasMyGames: true, hasInvitations: true }),
			),
		).toBe("games-active-past");
	});

	test("paid tier with no games → recruitment, not private-games", () => {
		expect(firstVisibleGamesScreen(state({ isPaidOrDev: true }))).toBe(
			"games-recruitment",
		);
	});
});
