// Battle-report fetcher used by the Battle Viewer page.
//
// Phase 27 ships the BattleViewer as a logically isolated component
// that accepts a `BattleReport` matching `pkg/model/report/battle.go`.
// This module owns the type mirror and a single `fetchBattle` entry
// point. In synthetic mode (development & e2e fixtures), the loader
// falls back to a local fixture so the UI tests don't depend on a
// running engine; otherwise it issues a real `GET` against the
// backend gateway route added in Phase 27 step 3.

import { isSyntheticGameId } from "./synthetic-report";
import { lookupSyntheticBattle } from "./synthetic-battle";

/**
 * BattleReport is the wire shape returned by the engine endpoint
 * `GET /api/v1/battle/:turn/:uuid` and forwarded by the backend
 * gateway as `GET /api/v1/user/games/{game_id}/battles/{turn}/{battle_id}`.
 * Fields mirror `pkg/model/report/battle.go`.
 */
export interface BattleReport {
	id: string;
	planet: number;
	planetName: string;
	races: Record<string, string>;
	ships: Record<string, BattleReportGroup>;
	protocol: BattleActionReport[];
}

export interface BattleReportGroup {
	race: string;
	className: string;
	tech: Record<string, number>;
	num: number;
	numLeft: number;
	loadType: string;
	loadQuantity: number;
	inBattle: boolean;
}

export interface BattleActionReport {
	a: number;
	sa: number;
	d: number;
	sd: number;
	x: boolean;
}

export class BattleFetchError extends Error {
	constructor(public readonly status: number, message: string) {
		super(message);
		this.name = "BattleFetchError";
	}
}

/**
 * fetchBattle returns the `BattleReport` for the supplied game, turn,
 * and battle id. In synthetic-report mode (DEV / e2e) the lookup is
 * served from `synthetic-battle.ts`; otherwise the function calls the
 * backend gateway route. Throws `BattleFetchError` with the upstream
 * status on validation or transport failure.
 */
export async function fetchBattle(
	gameId: string,
	turn: number,
	battleId: string,
): Promise<BattleReport> {
	if (isSyntheticGameId(gameId)) {
		const fixture = lookupSyntheticBattle(battleId);
		if (fixture === null) {
			throw new BattleFetchError(404, "battle not found");
		}
		return fixture;
	}
	const path = `/api/v1/user/games/${encodeURIComponent(gameId)}/battles/${turn}/${encodeURIComponent(battleId)}`;
	const response = await fetch(path, {
		headers: { Accept: "application/json" },
	});
	if (response.status === 404) {
		throw new BattleFetchError(404, "battle not found");
	}
	if (!response.ok) {
		throw new BattleFetchError(
			response.status,
			`battle fetch failed: ${response.status}`,
		);
	}
	return (await response.json()) as BattleReport;
}
