<!--
F8-11 battles table. Lists every battle the engine recorded for the
current turn (`Report.battle[]`) with a sortable planet/shots view.
Row click opens the existing Battle Viewer through
`activeView.select("battle", { battleId, turn })`, identical to the
`section-battles.svelte` and battle-marker entry points so a single
viewer wrapper keeps owning the data fetch.

Intentionally minimal: only the two scalars carried by the report's
`BattleSummary` (planet number and shot count). Participants /
observers / fleet mass live in the per-battle `BattleReport` and are
out of scope here — fetching them per row would mean N round trips
on every menu open.
-->
<script lang="ts">
	import { getContext } from "svelte";

	import type { ReportBattle, ReportPlanet } from "../../api/game-state";
	import { activeView } from "$lib/app-nav.svelte";
	import { i18n, type TranslationKey } from "$lib/i18n/index.svelte";
	import { planetLabel } from "./report/format";
	import {
		RENDERED_REPORT_CONTEXT_KEY,
		type RenderedReportSource,
	} from "$lib/rendered-report.svelte";
	import ViewState from "$lib/ui/view-state.svelte";
	import { formatInt } from "$lib/util/number-format";
	import {
		battlesTableState as persistent,
		type BattlesSortColumn as SortColumn,
	} from "./table-battles-state.svelte";

	const COLUMN_LABELS: Record<SortColumn, TranslationKey> = {
		planet: "game.table.battles.column.planet",
		shots: "game.table.battles.column.shots",
	};

	const COLUMNS: readonly SortColumn[] = ["planet", "shots"];

	const rendered = getContext<RenderedReportSource | undefined>(
		RENDERED_REPORT_CONTEXT_KEY,
	);

	const reportLoaded = $derived(
		rendered?.report !== null && rendered?.report !== undefined,
	);
	const battles = $derived<ReportBattle[]>(rendered?.report?.battles ?? []);
	const planets = $derived<ReportPlanet[]>(rendered?.report?.planets ?? []);
	const turn = $derived<number>(rendered?.report?.turn ?? 0);

	const sorted = $derived.by(() => {
		const list = [...battles];
		const dir = persistent.sortDirection === "asc" ? 1 : -1;
		list.sort((a, b) => compare(a, b, persistent.sortColumn) * dir);
		return list;
	});

	function compare(
		a: ReportBattle,
		b: ReportBattle,
		column: SortColumn,
	): number {
		switch (column) {
			case "planet":
				return a.planet - b.planet;
			case "shots":
				return a.shots - b.shots;
		}
	}

	function toggleSort(column: SortColumn): void {
		if (persistent.sortColumn === column) {
			persistent.sortDirection =
				persistent.sortDirection === "asc" ? "desc" : "asc";
			return;
		}
		persistent.sortColumn = column;
		// shots is most-interesting-largest-first; planet is naturally
		// ascending by number.
		persistent.sortDirection = column === "shots" ? "desc" : "asc";
	}

	function ariaSort(column: SortColumn): "ascending" | "descending" | "none" {
		if (persistent.sortColumn !== column) return "none";
		return persistent.sortDirection === "asc" ? "ascending" : "descending";
	}

	function openBattle(b: ReportBattle): void {
		activeView.select("battle", { battleId: b.id, turn });
	}
</script>

<section
	class="active-view"
	data-testid="active-view-table"
	data-entity="battles"
>
	<header>
		<h2>{i18n.t("game.table.battles.title")}</h2>
	</header>

	{#if !reportLoaded}
		<ViewState
			kind="loading"
			testid="battles-loading"
			message={i18n.t("game.table.battles.loading")}
		/>
	{:else if battles.length === 0}
		<ViewState
			kind="empty"
			testid="battles-empty"
			message={i18n.t("game.table.battles.empty")}
		/>
	{:else}
		<table class="grid" data-testid="battles-table">
			<thead>
				<tr>
					{#each COLUMNS as column (column)}
						<th
							aria-sort={ariaSort(column)}
							class:numeric={column === "shots"}
						>
							<button
								type="button"
								class="sort"
								data-testid="battles-column-{column}"
								onclick={() => toggleSort(column)}
							>
								{i18n.t(COLUMN_LABELS[column])}
								{#if persistent.sortColumn === column}
									<span class="sort-indicator" aria-hidden="true">
										{persistent.sortDirection === "asc" ? "▲" : "▼"}
									</span>
								{/if}
							</button>
						</th>
					{/each}
				</tr>
			</thead>
			<tbody>
				{#each sorted as b (b.id)}
					<tr
						data-testid="battles-row"
						data-id={b.id}
						onclick={() => openBattle(b)}
					>
						<td data-testid="battles-cell-planet">
							{planetLabel(b.planet, planets)}
						</td>
						<td class="numeric" data-testid="battles-cell-shots">
							{formatInt(b.shots)}
						</td>
					</tr>
				{/each}
			</tbody>
		</table>
	{/if}
</section>

<style>
	.active-view {
		padding: 1.5rem;
		font-family: system-ui, sans-serif;
		display: flex;
		flex-direction: column;
		gap: 1rem;
	}
	header {
		display: flex;
		flex-direction: column;
		gap: 0.5rem;
	}
	header h2 {
		margin: 0;
		font-size: 1.1rem;
	}
	.grid {
		border-collapse: collapse;
		width: 100%;
		font-variant-numeric: tabular-nums;
	}
	.grid th,
	.grid td {
		padding: 0.4rem 0.6rem;
		text-align: left;
		border-bottom: 1px solid var(--color-border-subtle);
		font-size: 0.85rem;
	}
	.grid th {
		color: var(--color-text-muted);
		text-transform: uppercase;
		letter-spacing: 0.04em;
		font-size: 0.75rem;
	}
	.grid th.numeric,
	.grid td.numeric {
		font-family: var(--font-mono);
		text-align: right;
	}
	.grid th.numeric .sort {
		justify-content: flex-end;
	}
	.grid tbody tr {
		cursor: pointer;
	}
	.grid tbody tr:hover {
		background: var(--color-surface);
	}
	.sort {
		font: inherit;
		font-size: inherit;
		text-transform: inherit;
		letter-spacing: inherit;
		color: inherit;
		background: transparent;
		border: none;
		padding: 0;
		cursor: pointer;
		display: inline-flex;
		gap: 0.3rem;
		align-items: baseline;
	}
	.sort-indicator {
		font-size: 0.7em;
	}
</style>
