import { describe, expect, test } from "vitest";
import type { MainWeaponId } from "~/modules/in-game-lists/types";
import { mainWeaponIds } from "~/modules/in-game-lists/weapon-ids";
import { damageTypeToWeaponType } from "../analyzer-constants";
import { buildStats } from "./stats";

describe("Analyze build", () => {
	test("Every main weapon has damage", () => {
		const weaponsWithoutDamage: MainWeaponId[] = [];

		for (const weaponSplId of mainWeaponIds) {
			const analyzed = buildStats({
				weaponSplId,
				hasTacticooler: false,
			});

			const hasDamage =
				analyzed.stats.damages.filter(
					(dmg) => damageTypeToWeaponType[dmg.type] === "MAIN",
				).length > 0;

			if (!hasDamage) {
				weaponsWithoutDamage.push(weaponSplId);
			}
		}

		expect(
			weaponsWithoutDamage.length,
			`Weapons without damage set: ${weaponsWithoutDamage.join(", ")}`,
		).toBe(0);
	});

	test("Ninja Squid decreases swim speed", () => {
		const analyzed = buildStats({
			weaponSplId: 0,
			hasTacticooler: false,
		});

		const analyzedWithNS = buildStats({
			weaponSplId: 0,
			mainOnlyAbilities: ["NS"],
			hasTacticooler: false,
		});

		expect(analyzed.stats.swimSpeed.value).toBeGreaterThan(
			analyzedWithNS.stats.swimSpeed.value,
		);
	});

	test("Tacticooler / RP calculated correctly", () => {
		const fullQR = buildStats({
			weaponSplId: 0,
			abilityPoints: new Map([["QR", 57]]),
			hasTacticooler: false,
		});

		const tacticooler = buildStats({
			weaponSplId: 0,
			abilityPoints: new Map([["QR", 57]]),
			hasTacticooler: true,
		});

		expect(
			fullQR.stats.quickRespawnTime.value,
			"Base QR should be same whether 57AP of QR or Tacticooler",
		).toBe(tacticooler.stats.quickRespawnTime.value);
		expect(
			fullQR.stats.quickRespawnTimeSplattedByRP.value,
			"Tacticooler splatted by RP should respawn faster than 57AP of QR",
		).toBeGreaterThan(tacticooler.stats.quickRespawnTimeSplattedByRP.value);
		expect(
			tacticooler.stats.quickRespawnTime.value,
			"Tacticooler should respawn faster than Tacticooler splatted by RP",
		).toBeLessThan(tacticooler.stats.quickRespawnTimeSplattedByRP.value);
	});

	test("Accounts for Jr. big ink tank with sub weapon ink consumption %", () => {
		const analyzedDualieSquelchers = buildStats({
			weaponSplId: 5030,
			hasTacticooler: false,
		});

		const analyzedJr = buildStats({
			weaponSplId: 10,
			hasTacticooler: false,
		});

		expect(
			analyzedDualieSquelchers.stats.subWeaponInkConsumptionPercentage.value,
		).toBeGreaterThan(analyzedJr.stats.subWeaponInkConsumptionPercentage.value);
	});

	const subPowerApToQuickSuperJumpAp = new Map([
		[0, 0],
		[3, 4],
		[6, 9],
		[13, 18],
		[28, 36],
		[57, 57],
	]);

	test("Sub Power Up Beakon AP boost matches Lean", () => {
		for (const [subPowerAp, quickSuperJumpAp] of subPowerApToQuickSuperJumpAp) {
			const analyzed = buildStats({
				weaponSplId: 1011,
				abilityPoints: new Map([["BRU" as const, subPowerAp]]),
				hasTacticooler: false,
			});

			expect(
				analyzed.stats.subQsjBoost?.value,
				`Wrong AP boost for ${subPowerAp}AP of Sub Power Up: ${
					analyzed.stats.subQsjBoost!.value
				} (expected ${quickSuperJumpAp}))`,
			).toBe(quickSuperJumpAp);
		}
	});
});
