// Phase 29 component coverage for `lib/active-view/map-toggles.svelte`.
// The popover is a thin view of the `GameStateStore` runes —
// every control fires `setMapToggle` / `setWrapMode` on the store
// and reads the current state through `store.mapToggles` /
// `store.wrapMode`. The tests assert the wiring, the default
// rendering, and the popover lifecycle (open / Escape close).

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 MapTogglesControl from "../src/lib/active-view/map-toggles.svelte";
import {
	DEFAULT_MAP_TOGGLES,
	GameStateStore,
} from "../src/lib/game-state.svelte";

function buildStore(): GameStateStore {
	const store = new GameStateStore();
	store.status = "ready";
	store.wrapMode = "torus";
	store.mapToggles = { ...DEFAULT_MAP_TOGGLES };
	return store;
}

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

describe("MapTogglesControl", () => {
	test("trigger renders and the popover is closed by default", () => {
		const store = buildStore();
		const ui = render(MapTogglesControl, { props: { store } });
		const trigger = ui.getByTestId("map-toggles-trigger");
		expect(trigger).toBeInTheDocument();
		expect(trigger).toHaveAttribute("aria-expanded", "false");
		// The 44+ px touch-target is enforced through CSS; jsdom does
		// not parse scoped Svelte styles for `getComputedStyle`, so the
		// dimension is verified in the Playwright e2e where real
		// browsers compute the rule.
		expect(ui.queryByTestId("map-toggles-surface")).toBeNull();
	});

	test("clicking the trigger opens the popover with defaults applied", async () => {
		const store = buildStore();
		const ui = render(MapTogglesControl, { props: { store } });
		await fireEvent.click(ui.getByTestId("map-toggles-trigger"));
		const surface = ui.getByTestId("map-toggles-surface");
		expect(surface).toBeInTheDocument();
		expect(ui.getByTestId("map-toggles-hyperspace-groups")).toBeChecked();
		expect(ui.getByTestId("map-toggles-incoming-groups")).toBeChecked();
		expect(ui.getByTestId("map-toggles-unidentified-groups")).toBeChecked();
		expect(ui.getByTestId("map-toggles-cargo-routes")).toBeChecked();
		expect(ui.getByTestId("map-toggles-battle-markers")).toBeChecked();
		expect(ui.getByTestId("map-toggles-bombing-markers")).toBeChecked();
		expect(ui.getByTestId("map-toggles-foreign-planets")).toBeChecked();
		expect(ui.getByTestId("map-toggles-uninhabited-planets")).toBeChecked();
		expect(ui.getByTestId("map-toggles-unidentified-planets")).toBeChecked();
		expect(ui.getByTestId("map-toggles-unreachable-planets")).toBeChecked();
		expect(ui.getByTestId("map-toggles-visible-hyperspace")).toBeChecked();
		expect(ui.getByTestId("map-toggles-wrap-torus")).toBeChecked();
		expect(ui.getByTestId("map-toggles-wrap-no-wrap")).not.toBeChecked();
	});

	test("flipping a checkbox calls setMapToggle with the new value", async () => {
		const store = buildStore();
		const setMapToggle = vi
			.spyOn(store, "setMapToggle")
			.mockResolvedValue(undefined);
		const ui = render(MapTogglesControl, { props: { store } });
		await fireEvent.click(ui.getByTestId("map-toggles-trigger"));
		await fireEvent.click(ui.getByTestId("map-toggles-battle-markers"));
		expect(setMapToggle).toHaveBeenCalledWith("battleMarkers", false);
		await fireEvent.click(ui.getByTestId("map-toggles-foreign-planets"));
		expect(setMapToggle).toHaveBeenCalledWith("foreignPlanets", false);
	});

	test("battle and bombing toggles are independent", async () => {
		const store = buildStore();
		const setMapToggle = vi
			.spyOn(store, "setMapToggle")
			.mockResolvedValue(undefined);
		const ui = render(MapTogglesControl, { props: { store } });
		await fireEvent.click(ui.getByTestId("map-toggles-trigger"));
		await fireEvent.click(ui.getByTestId("map-toggles-battle-markers"));
		expect(setMapToggle).toHaveBeenCalledTimes(1);
		expect(setMapToggle).toHaveBeenCalledWith("battleMarkers", false);
		// No spillover into bombingMarkers.
		expect(setMapToggle).not.toHaveBeenCalledWith("bombingMarkers", false);
	});

	test("selecting the no-wrap radio calls setWrapMode", async () => {
		const store = buildStore();
		const setWrapMode = vi
			.spyOn(store, "setWrapMode")
			.mockResolvedValue(undefined);
		const ui = render(MapTogglesControl, { props: { store } });
		await fireEvent.click(ui.getByTestId("map-toggles-trigger"));
		await fireEvent.click(ui.getByTestId("map-toggles-wrap-no-wrap"));
		expect(setWrapMode).toHaveBeenCalledWith("no-wrap");
	});

	test("Escape closes the popover", async () => {
		const store = buildStore();
		const ui = render(MapTogglesControl, { props: { store } });
		await fireEvent.click(ui.getByTestId("map-toggles-trigger"));
		expect(ui.getByTestId("map-toggles-surface")).toBeInTheDocument();
		await fireEvent.keyDown(document, { key: "Escape" });
		expect(ui.queryByTestId("map-toggles-surface")).toBeNull();
	});

	test("clicking outside the popover closes it", async () => {
		const store = buildStore();
		const ui = render(MapTogglesControl, { props: { store } });
		await fireEvent.click(ui.getByTestId("map-toggles-trigger"));
		expect(ui.getByTestId("map-toggles-surface")).toBeInTheDocument();
		// Synthetic outside click — fire on document with the trigger
		// removed from the click target chain.
		await fireEvent.click(document.body);
		expect(ui.queryByTestId("map-toggles-surface")).toBeNull();
	});
});
