// Phase 27 unit tests for battle and bombing map markers.

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

import type { GameReport } from "../src/api/game-state";
import {
	battleMarkerStrokeWidth,
	BATTLE_MARKER_COLOR,
	BOMBING_MARKER_COLOR_DAMAGED,
	BOMBING_MARKER_COLOR_WIPED,
	buildBattleAndBombingMarkers,
} from "../src/map/battle-markers";
import { EMPTY_SHIP_GROUPS } from "./helpers/empty-ship-groups";

describe("battleMarkerStrokeWidth", () => {
	it("clamps to 1 px at one shot", () => {
		expect(battleMarkerStrokeWidth(1)).toBe(1);
	});

	it("clamps to 5 px at 100 shots", () => {
		expect(battleMarkerStrokeWidth(100)).toBe(5);
	});

	it("caps above 100 shots at 5 px", () => {
		expect(battleMarkerStrokeWidth(250)).toBe(5);
	});

	it("interpolates linearly between 1 and 100 shots", () => {
		// ~halfway: 50 shots → 1 + 49 * 4 / 99 ≈ 2.98
		expect(battleMarkerStrokeWidth(50)).toBeCloseTo(2.98, 2);
	});
});

function makeReport(overrides: Partial<GameReport>): GameReport {
	return {
		turn: 1,
		mapWidth: 200,
		mapHeight: 200,
		planetCount: 0,
		race: "Earthlings",
		planets: [],
		localShipClass: [],
		routes: [],
		localPlayerDrive: 0,
		localPlayerWeapons: 0,
		localPlayerShields: 0,
		localPlayerCargo: 0,
		...EMPTY_SHIP_GROUPS,
		...overrides,
	};
}

describe("buildBattleAndBombingMarkers", () => {
	it("returns no primitives when both battles and bombings are empty", () => {
		const report = makeReport({});
		const out = buildBattleAndBombingMarkers(report);
		expect(out.primitives).toEqual([]);
		expect(out.lookup.size).toBe(0);
	});

	it("emits two yellow lines through opposite corners of the planet square per battle", () => {
		const report = makeReport({
			planets: [
				{
					number: 4,
					name: "Test",
					kind: "local",
					x: 10,
					y: 20,
					size: 50,
					resources: 0,
					industryStockpile: 0,
					materialsStockpile: 0,
					population: 0,
					colonists: 0,
					industry: 0,
					freeIndustry: 0,
					production: "MAT",
					owner: null,
				},
			],
			battles: [
				{ id: "11111111-1111-1111-1111-111111111111", planet: 4, shots: 100 },
			],
		});

		const out = buildBattleAndBombingMarkers(report);
		const lines = out.primitives.filter((p) => p.kind === "line");
		expect(lines).toHaveLength(2);
		// Same yellow colour, 5 px wide for a 100-shot battle.
		for (const l of lines) {
			expect(l.style.strokeColor).toBe(BATTLE_MARKER_COLOR);
			expect(l.style.strokeWidthPx).toBe(5);
		}
		// First line: top-left → bottom-right corner of the planet square.
		const [a, b] = lines as Array<typeof lines[number] & { x1: number; y1: number; x2: number; y2: number }>;
		expect(a.x1).toBeLessThan(a.x2);
		expect(a.y1).toBeLessThan(a.y2);
		// Second line: top-right → bottom-left.
		expect(b.x1).toBeLessThan(b.x2);
		expect(b.y1).toBeGreaterThan(b.y2);
	});

	it("skips battles whose planet is not in the planet list", () => {
		const report = makeReport({
			battles: [
				{ id: "11111111-1111-1111-1111-111111111111", planet: 99, shots: 4 },
			],
		});
		const out = buildBattleAndBombingMarkers(report);
		expect(out.primitives).toHaveLength(0);
	});

	it("emits one yellow ring per damaged bombing and red per wiped", () => {
		const report = makeReport({
			planets: [
				{
					number: 1,
					name: "A",
					kind: "local",
					x: 1,
					y: 2,
					size: 50,
					resources: 0,
					industryStockpile: 0,
					materialsStockpile: 0,
					population: 0,
					colonists: 0,
					industry: 0,
					freeIndustry: 0,
					production: "MAT",
					owner: null,
				},
				{
					number: 2,
					name: "B",
					kind: "local",
					x: 5,
					y: 6,
					size: 50,
					resources: 0,
					industryStockpile: 0,
					materialsStockpile: 0,
					population: 0,
					colonists: 0,
					industry: 0,
					freeIndustry: 0,
					production: "MAT",
					owner: null,
				},
			],
			bombings: [
				{
					planetNumber: 1,
					planet: "A",
					owner: "X",
					attacker: "Y",
					production: "MAT",
					industry: 0,
					population: 0,
					colonists: 0,
					industryStockpile: 0,
					materialsStockpile: 0,
					attackPower: 1,
					wiped: false,
				},
				{
					planetNumber: 2,
					planet: "B",
					owner: "X",
					attacker: "Y",
					production: "MAT",
					industry: 0,
					population: 0,
					colonists: 0,
					industryStockpile: 0,
					materialsStockpile: 0,
					attackPower: 1,
					wiped: true,
				},
			],
		});

		const out = buildBattleAndBombingMarkers(report);
		const rings = out.primitives.filter((p) => p.kind === "circle");
		expect(rings).toHaveLength(2);
		expect(rings[0].style.strokeColor).toBe(BOMBING_MARKER_COLOR_DAMAGED);
		expect(rings[1].style.strokeColor).toBe(BOMBING_MARKER_COLOR_WIPED);
	});
});
