// Phase 26 turn-navigator component tests. The navigator owns three
// affordances: arrows that step ±1 through history, a clickable
// `turn N` button that opens the full popover, and the popover rows
// themselves. The store under test is a real `GameStateStore`
// instance seeded into Svelte context — the navigator never calls
// the network in tests because we override `viewTurn` /
// `returnToCurrent` with `vi.fn` spies.

import "@testing-library/jest-dom/vitest";
import { fireEvent, render } from "@testing-library/svelte";
import { beforeEach, describe, expect, test, vi } from "vitest";

import { i18n } from "../src/lib/i18n/index.svelte";
import TurnNavigator from "../src/lib/header/turn-navigator.svelte";
import {
	GAME_STATE_CONTEXT_KEY,
	GameStateStore,
} from "../src/lib/game-state.svelte";

function buildStore(opts: {
	currentTurn: number;
	viewedTurn: number;
	ready?: boolean;
}): GameStateStore {
	const store = new GameStateStore();
	store.currentTurn = opts.currentTurn;
	store.viewedTurn = opts.viewedTurn;
	store.status = opts.ready === false ? "loading" : "ready";
	return store;
}

beforeEach(() => {
	i18n.resetForTests("en");
});

describe("TurnNavigator", () => {
	test("renders `turn ?` when the store is not ready yet", () => {
		const store = buildStore({ currentTurn: 0, viewedTurn: 0, ready: false });
		const ui = render(TurnNavigator, {
			context: new Map([[GAME_STATE_CONTEXT_KEY, store]]),
		});
		expect(ui.getByTestId("turn-navigator-trigger")).toHaveTextContent(
			"turn ?",
		);
		expect(ui.getByTestId("turn-navigator-trigger")).toBeDisabled();
	});

	test("prev arrow disabled at viewedTurn = 0", () => {
		const ui = render(TurnNavigator, {
			context: new Map([
				[
					GAME_STATE_CONTEXT_KEY,
					buildStore({ currentTurn: 4, viewedTurn: 0 }),
				],
			]),
		});
		expect(ui.getByTestId("turn-navigator-prev")).toBeDisabled();
		expect(ui.getByTestId("turn-navigator-next")).not.toBeDisabled();
	});

	test("next arrow disabled at viewedTurn = currentTurn", () => {
		const ui = render(TurnNavigator, {
			context: new Map([
				[
					GAME_STATE_CONTEXT_KEY,
					buildStore({ currentTurn: 4, viewedTurn: 4 }),
				],
			]),
		});
		expect(ui.getByTestId("turn-navigator-prev")).not.toBeDisabled();
		expect(ui.getByTestId("turn-navigator-next")).toBeDisabled();
	});

	test("prev arrow steps to viewedTurn - 1 via viewTurn", async () => {
		const store = buildStore({ currentTurn: 4, viewedTurn: 4 });
		const viewTurn = vi
			.spyOn(store, "viewTurn")
			.mockResolvedValue(undefined);
		const returnToCurrent = vi
			.spyOn(store, "returnToCurrent")
			.mockResolvedValue(undefined);
		const ui = render(TurnNavigator, {
			context: new Map([[GAME_STATE_CONTEXT_KEY, store]]),
		});
		await fireEvent.click(ui.getByTestId("turn-navigator-prev"));
		expect(viewTurn).toHaveBeenCalledWith(3);
		expect(returnToCurrent).not.toHaveBeenCalled();
	});

	test("next arrow at one-step-from-current routes through returnToCurrent", async () => {
		const store = buildStore({ currentTurn: 4, viewedTurn: 3 });
		const viewTurn = vi
			.spyOn(store, "viewTurn")
			.mockResolvedValue(undefined);
		const returnToCurrent = vi
			.spyOn(store, "returnToCurrent")
			.mockResolvedValue(undefined);
		const ui = render(TurnNavigator, {
			context: new Map([[GAME_STATE_CONTEXT_KEY, store]]),
		});
		await fireEvent.click(ui.getByTestId("turn-navigator-next"));
		expect(returnToCurrent).toHaveBeenCalledTimes(1);
		expect(viewTurn).not.toHaveBeenCalled();
	});

	test("trigger opens the popover with every turn in descending order", async () => {
		const store = buildStore({ currentTurn: 3, viewedTurn: 1 });
		const ui = render(TurnNavigator, {
			context: new Map([[GAME_STATE_CONTEXT_KEY, store]]),
		});
		await fireEvent.click(ui.getByTestId("turn-navigator-trigger"));
		const list = ui.getByTestId("turn-navigator-list");
		expect(list).toBeInTheDocument();

		const rows = list.querySelectorAll("button[role='menuitem']");
		expect(rows.length).toBe(4);
		expect(rows[0]).toHaveAttribute(
			"data-testid",
			"turn-navigator-item-3",
		);
		expect(rows[3]).toHaveAttribute(
			"data-testid",
			"turn-navigator-item-0",
		);
		// Current-turn row carries the badge.
		const currentRow = ui.getByTestId("turn-navigator-item-3");
		expect(currentRow.querySelector("[data-testid='turn-navigator-current-badge']"))
			.not.toBeNull();
		// Other rows do not carry a badge.
		const otherRow = ui.getByTestId("turn-navigator-item-2");
		expect(otherRow.querySelector("[data-testid='turn-navigator-current-badge']"))
			.toBeNull();
	});

	test("selecting a past row delegates to viewTurn(N)", async () => {
		const store = buildStore({ currentTurn: 3, viewedTurn: 3 });
		const viewTurn = vi
			.spyOn(store, "viewTurn")
			.mockResolvedValue(undefined);
		const returnToCurrent = vi
			.spyOn(store, "returnToCurrent")
			.mockResolvedValue(undefined);
		const ui = render(TurnNavigator, {
			context: new Map([[GAME_STATE_CONTEXT_KEY, store]]),
		});
		await fireEvent.click(ui.getByTestId("turn-navigator-trigger"));
		await fireEvent.click(ui.getByTestId("turn-navigator-item-1"));
		expect(viewTurn).toHaveBeenCalledWith(1);
		expect(returnToCurrent).not.toHaveBeenCalled();
	});

	test("selecting the current row delegates to returnToCurrent", async () => {
		const store = buildStore({ currentTurn: 3, viewedTurn: 1 });
		const viewTurn = vi
			.spyOn(store, "viewTurn")
			.mockResolvedValue(undefined);
		const returnToCurrent = vi
			.spyOn(store, "returnToCurrent")
			.mockResolvedValue(undefined);
		const ui = render(TurnNavigator, {
			context: new Map([[GAME_STATE_CONTEXT_KEY, store]]),
		});
		await fireEvent.click(ui.getByTestId("turn-navigator-trigger"));
		await fireEvent.click(ui.getByTestId("turn-navigator-item-3"));
		expect(returnToCurrent).toHaveBeenCalledTimes(1);
		expect(viewTurn).not.toHaveBeenCalled();
	});
});
