// Per-game selection state: which on-map object the user is
// currently inspecting. Phase 13 modelled planets only; Phase 19
// widened the union to ship groups (own / foreign / incoming /
// unidentified).
//
// The store is in-memory only: lifetime matches the in-game shell
// layout instance, which itself is preserved across active-view
// switches inside `/games/:id/*`. Persisting selection across
// reloads is intentionally out of scope — the Phase 13 acceptance
// criterion calls out "across view switches", and survival across a
// reload would be a surprising contrast with the empty-state copy
// users see on first load.
//
// Like `GameStateStore` and `OrderDraftStore`, the store is
// instantiated by the layout and shared with descendants through
// Svelte context. The map view pushes selection events into it; the
// inspector tab and the mobile bottom-sheet read from it.
//
// The store deliberately carries no Svelte component imports so it
// can be tested directly without rendering any UI.

/**
 * ShipGroupRef identifies a ship group inside the current report.
 * `local` groups carry a stable engine UUID (passed through
 * `report.localGroup.id` and used by the upcoming Phase 20 order
 * envelopes). The remaining variants do not — they are addressed by
 * their position in the matching report array, which is fine for
 * the read-only inspector: a new report load reseeds the store and
 * any stale index resolves to a missing entry on lookup, collapsing
 * the inspector cleanly.
 */
export type ShipGroupRef =
	| { variant: "local"; id: string }
	| { variant: "other"; index: number }
	| { variant: "incoming"; index: number }
	| { variant: "unidentified"; index: number };

/**
 * Selected describes the currently selected map object. The
 * discriminated union is closed: every map-clickable surface maps
 * to one of these variants. Future phases (e.g. fleet selection)
 * extend by adding a new branch — extension is purely additive.
 */
export type Selected =
	| { kind: "planet"; id: number }
	| { kind: "shipGroup"; ref: ShipGroupRef };

/**
 * SELECTION_CONTEXT_KEY is the Svelte context key the in-game shell
 * layout uses to expose its `SelectionStore` instance to descendants.
 * Map view, inspector tab, and the mobile bottom-sheet resolve the
 * store via `getContext(SELECTION_CONTEXT_KEY)`.
 */
export const SELECTION_CONTEXT_KEY = Symbol("selection");

export class SelectionStore {
	selected: Selected | null = $state(null);

	private destroyed = false;

	/**
	 * selectPlanet sets the active selection to the planet identified
	 * by its engine `number`. A no-op once the store has been disposed.
	 */
	selectPlanet(id: number): void {
		if (this.destroyed) return;
		this.selected = { kind: "planet", id };
	}

	/**
	 * selectShipGroup sets the active selection to a ship group. The
	 * `ref` discriminator carries the variant + the right id shape for
	 * lookup against the current report.
	 */
	selectShipGroup(ref: ShipGroupRef): void {
		if (this.destroyed) return;
		this.selected = { kind: "shipGroup", ref };
	}

	/**
	 * clear drops the current selection. The mobile sheet's close
	 * button calls this; otherwise selection persists across active-
	 * view switches.
	 */
	clear(): void {
		if (this.destroyed) return;
		this.selected = null;
	}

	dispose(): void {
		this.destroyed = true;
		this.selected = null;
	}
}
