import * as THREE from "three";
import type { SceneNode } from "./viewerScenePrimitives";
import type {
  CelestialSnapshot,
  ClaimSnapshot,
  ConstructionSiteSnapshot,
  FactionSnapshot,
  MarketOrderSnapshot,
  PlanetSnapshot,
  PolicySetSnapshot,
  ResourceNodeSnapshot,
  ShipSnapshot,
  SimulationEventRecord,
  StationSnapshot,
  SystemSnapshot,
  OrbitalSimulationSnapshot,
  GeopoliticalStateSnapshot,
} from "./contracts";

export type PovLevel = "local" | "system" | "galaxy";
export type SelectionGroup = "ships" | "structures" | "celestials";
export type DragMode = "pan" | "pinch";
export type CameraMode = "tactical" | "follow";

export type Selectable =
  | { kind: "ship"; id: string }
  | { kind: "station"; id: string }
  | { kind: "node"; id: string }
  | { kind: "celestial"; id: string }
  | { kind: "claim"; id: string }
  | { kind: "construction-site"; id: string }
  | { kind: "system"; id: string }
  | { kind: "planet"; systemId: string; planetIndex: number }
  | { kind: "moon"; systemId: string; planetIndex: number; moonIndex: number };

export interface ShipVisual {
  systemId: string;
  mesh: SceneNode;
  icon: SceneNode;
  iconBaseScale: number;
  startPosition: THREE.Vector3;
  authoritativePosition: THREE.Vector3;
  targetPosition: THREE.Vector3;
  velocity: THREE.Vector3;
  receivedAtMs: number;
  blendDurationMs: number;
}

export interface PlanetVisual {
  systemId: string;
  planet: PlanetSnapshot;
  orbit: SceneNode;
  mesh: SceneNode;
  icon: SceneNode;
  iconBaseScale: number;
  ring?: SceneNode;
  moons: MoonVisual[];
}

export interface MoonVisual {
  systemId: string;
  planetIndex: number;
  moonIndex: number;
  mesh: SceneNode;
  icon: SceneNode;
  iconBaseScale: number;
  orbit: SceneNode;
}

export type OrbitalAnchor =
  | { kind: "star" }
  | { kind: "planet"; planetIndex: number }
  | { kind: "moon"; planetIndex: number; moonIndex: number };

export interface NodeVisual {
  systemId: string;
  mesh: SceneNode;
  icon: SceneNode;
  sourceKind: string;
  anchor: OrbitalAnchor;
  localPosition: THREE.Vector3;
  orbitRadius: number;
  orbitPhase: number;
  orbitInclination: number;
}

export interface CelestialVisual {
  id: string;
  systemId: string;
  mesh: SceneNode;
  icon: SceneNode;
  iconBaseScale: number;
  kind: string;
  orbitalAnchor: THREE.Vector3;
}

export interface ClaimVisual {
  id: string;
  celestialId: string;
  systemId: string;
  mesh: SceneNode;
  icon: SceneNode;
  localPosition: THREE.Vector3;
}

export interface ConstructionSiteVisual {
  id: string;
  celestialId: string;
  systemId: string;
  mesh: SceneNode;
  icon: SceneNode;
  localPosition: THREE.Vector3;
}

export interface StructureVisual {
  id: string;
  systemId: string;
  mesh: SceneNode;
  icon: SceneNode;
  anchor: OrbitalAnchor;
  orbitRadius: number;
  orbitPhase: number;
  orbitInclination: number;
  localPosition: THREE.Vector3;
}

export interface SystemVisual {
  galaxyRoot: SceneNode;        // lives in galaxyScene (star dot + shell reticle)
  systemRoot: SceneNode;        // added/removed from systemScene when system becomes active/inactive
  starCluster: SceneNode;
  icon: SceneNode;              // star dot sprite (child of galaxyRoot)
  shellReticle: SceneNode;      // reticle sprite (child of galaxyRoot)
  shellReticleBaseScale: number;
  detailGroup: SceneNode;       // planets + moons (child of systemRoot)
  galaxyPosition: THREE.Vector3;
}

export interface WorldState {
  label: string;
  seed: number;
  sequence: number;
  tickIntervalMs: number;
  orbitalTimeSeconds: number;
  orbitalSimulation: OrbitalSimulationSnapshot;
  generatedAtUtc: string;
  systems: Map<string, SystemSnapshot>;
  celestials: Map<string, CelestialSnapshot>;
  nodes: Map<string, ResourceNodeSnapshot>;
  stations: Map<string, StationSnapshot>;
  claims: Map<string, ClaimSnapshot>;
  constructionSites: Map<string, ConstructionSiteSnapshot>;
  marketOrders: Map<string, MarketOrderSnapshot>;
  policies: Map<string, PolicySetSnapshot>;
  ships: Map<string, ShipSnapshot>;
  factions: Map<string, FactionSnapshot>;
  geopolitics: GeopoliticalStateSnapshot | null;
  recentEvents: SimulationEventRecord[];
}

export interface NetworkSample {
  atMs: number;
  bytes: number;
}

export interface NetworkStats {
  snapshotBytes: number;
  deltasReceived: number;
  deltaBytes: number;
  lastDeltaBytes: number;
  lastEntityChanges: number;
  eventsReceived: number;
  streamConnected: boolean;
  streamOpenedAtMs?: number;
  lastDeltaAtMs?: number;
  throughputSamples: NetworkSample[];
}

export interface PerformanceSample {
  atMs: number;
  frameMs: number;
}

export interface PerformanceStats {
  frameSamples: PerformanceSample[];
  lastFrameMs: number;
  lastPanelUpdateAtMs: number;
}
