// Smoke test for the Phase 30 calculator bridge against the real
// (TinyGo-built) core.wasm. The calc-model and component suites use a
// fake Core; this file boots the actual WASM module to confirm every new
// function is registered in `ui/wasm/main.go` and marshals correctly —
// including the object return of `produceShipsInTurn` and the `null`
// infeasible result of the solvers. Requires `make wasm` to have run.

import { beforeAll, describe, expect, test } from "vitest";
import type { Core } from "../src/platform/core/index";
import { loadWasmCoreForTest } from "./setup-wasm";

let core: Core;

beforeAll(async () => {
	core = await loadWasmCoreForTest();
});

describe("WasmCore calculator bridge (Phase 30)", () => {
	test("combat results", () => {
		expect(core.effectiveAttack({ weapons: 15, weaponsTech: 1.5 })).toBeCloseTo(
			22.5,
			9,
		);
		expect(
			core.effectiveDefence({ shields: 20, shieldsTech: 1, fullMass: 45 }),
		).toBeCloseTo((20 / Math.cbrt(45)) * Math.cbrt(30), 6);
		expect(
			core.bombingPower({ weapons: 30, weaponsTech: 1, armament: 3, number: 1 }),
		).toBeCloseTo(139.29503, 3);
	});

	test("planet build", () => {
		expect(
			core.shipBuildCost({ shipMass: 10, material: 3, resources: 0.5 }),
		).toBeCloseTo(114, 9);
		const r = core.produceShipsInTurn({
			productionAvailable: 100,
			material: 100,
			resources: 10,
			shipMass: 1,
		});
		expect(r).toEqual({
			ships: 10,
			materialLeft: 90,
			productionUsed: 0,
			progress: 0,
		});
	});

	test("goal-seek solvers, including infeasible", () => {
		expect(
			core.weaponsForAttack({ targetAttack: 30, weaponsTech: 1.5 }),
		).toBeCloseTo(20, 9);
		expect(
			core.cargoForEmptyMass({ targetEmptyMass: 42, restMass: 30 }),
		).toBeCloseTo(12, 9);
		expect(
			core.loadForFullMass({ targetFullMass: 65, emptyMass: 45, cargoTech: 1 }),
		).toBeCloseTo(20, 9);
		const shields = core.shieldsForDefence({
			targetDefence: 5,
			shieldsTech: 1,
			restMass: 40,
		});
		expect(shields).not.toBeNull();
		expect(shields as number).toBeGreaterThan(0);
		// Speed at/above the stripped-hull ceiling (20 × driveTech) is
		// unreachable: the bridge returns null.
		expect(
			core.driveForSpeed({ targetSpeed: 100, driveTech: 1.2, restMass: 35 }),
		).toBeNull();
	});

	test("ceil3 rounds up to three decimals", () => {
		expect(core.ceil3({ value: 5.0003 })).toBeCloseTo(5.001, 9);
		expect(core.ceil3({ value: 4.2761 })).toBeCloseTo(4.277, 9);
		expect(core.ceil3({ value: 5 })).toBeCloseTo(5, 9);
	});
});
