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

import {
	computeReachCircles,
	reachBound,
	REACH_CIRCLE_ID_PREFIX,
} from "../src/map/reach-circles";

const CENTER = { x: 500, y: 500 };

describe("computeReachCircles", () => {
	test("no circles for a non-positive speed", () => {
		expect(computeReachCircles(CENTER, 0, 1000, 1000, "torus")).toEqual([]);
		expect(computeReachCircles(CENTER, -5, 1000, 1000, "torus")).toEqual([]);
	});

	test("torus: a slow ship shows all three rings", () => {
		// bound = min(1000,1000)/2 = 500; speed 100 keeps every ring inside.
		const circles = computeReachCircles(CENTER, 100, 1000, 1000, "torus");
		expect(circles.map((c) => c.radius)).toEqual([100, 200, 300]);
		expect(circles[0].id).toBe(REACH_CIRCLE_ID_PREFIX + 1);
		expect(circles[0].style.strokeColor).toBeDefined();
	});

	test("torus: a ship reaching the wrap midpoint shows one ring", () => {
		// speed 500 hits the bound on turn 1, so turn 2 is dropped.
		const circles = computeReachCircles(CENTER, 500, 1000, 1000, "torus");
		expect(circles).toHaveLength(1);
		expect(circles[0].radius).toBe(500);
	});

	test("torus: a mid-speed ship shows two rings", () => {
		// speed 300: ring 1 = 300 (< 500), ring 2 = 600; ring 3 dropped
		// because 2 × 300 = 600 ≥ 500.
		const circles = computeReachCircles(CENTER, 300, 1000, 1000, "torus");
		expect(circles.map((c) => c.radius)).toEqual([300, 600]);
	});

	test("no-wrap: the bound is the farthest corner", () => {
		// origin at a corner → farthest corner is the diagonal.
		expect(reachBound({ x: 0, y: 0 }, 1000, 1000, "no-wrap")).toBeCloseTo(
			Math.hypot(1000, 1000),
			6,
		);
		const circles = computeReachCircles(
			{ x: 0, y: 0 },
			500,
			1000,
			1000,
			"no-wrap",
		);
		// bound ≈ 1414, so all three rings fit.
		expect(circles.map((c) => c.radius)).toEqual([500, 1000, 1500]);
	});
});
