import type { StationSnapshot } from "./contractsInfrastructure";
import type { FactionSnapshot } from "./contractsFactions";
import type {
  HudProgressBar,
  OpsFactionCardState,
  OpsShipCardState,
  OpsStationCardState,
  OpsStripState,
} from "./viewerHudState";
import { describeShipCurrentAction, describeShipLocation, describeShipState } from "./viewerSelection";
import { getShipBehaviorLabel, getShipOrderLabel } from "./shipAutomationPresentation";
import type { CameraMode, Selectable, WorldState, PovLevel } from "./viewerTypes";
import { usePlayerFactionStore } from "./ui/stores/playerFactionStore";
import { viewerPinia } from "./ui/stores/pinia";

function buildFactionCard(world: WorldState, faction: FactionSnapshot): OpsFactionCardState {
  const playerFaction = usePlayerFactionStore(viewerPinia).playerFaction;
  if (playerFaction && playerFaction.sovereignFactionId === faction.id) {
    const selectedDirective = playerFaction.directives[0];
    return {
      kind: "faction",
      id: faction.id,
      label: `${faction.label} Command`,
      stateLines: [
        `Player ${playerFaction.assetRegistry.shipIds.length} ships · ${playerFaction.assetRegistry.stationIds.length} stations`,
        `Groups ${playerFaction.fleets.length + playerFaction.taskForces.length + playerFaction.stationGroups.length + playerFaction.economicRegions.length + playerFaction.fronts.length + playerFaction.reserves.length}`,
        `Intent ${playerFaction.strategicIntent.strategicPosture} · ${playerFaction.strategicIntent.economicPosture}`,
        `Alerts ${playerFaction.alerts.length} · Decisions ${playerFaction.decisionLog.length}`,
        `Lead ${selectedDirective ? `${selectedDirective.behaviorKind} · ${selectedDirective.scopeKind}` : "no active directives"}`,
      ],
      priorities: [
        { label: "Reserve", value: `${Math.round(playerFaction.strategicIntent.desiredReserveRatio * 100)}%` },
        { label: "Auto", value: `${Number(playerFaction.strategicIntent.allowDelegatedEconomicAutomation)}/${Number(playerFaction.strategicIntent.allowDelegatedCombatAutomation)}` },
      ],
    };
  }

  const strategicState = faction.strategicState;
  const economic = strategicState.economicAssessment;
  const activeCampaigns = strategicState.campaigns.filter((campaign) => campaign.status === "active");
  const activeTheaters = strategicState.theaters.filter((theater) => theater.status === "active");
  const activeWars = world.geopolitics?.diplomacy.wars.filter((war) => war.factionAId === faction.id || war.factionBId === faction.id).length ?? 0;
  const contestedSystems = world.geopolitics?.territory.controlStates.filter((state) =>
    state.isContested && (state.controllerFactionId === faction.id || state.primaryClaimantFactionId === faction.id || state.claimantFactionIds.includes(faction.id))).length ?? 0;
  const leadCampaign = [...strategicState.campaigns]
    .sort((left, right) => right.priority - left.priority)[0];
  const leadTheater = [...strategicState.theaters]
    .sort((left, right) => right.priority - left.priority)[0];
  const latestDecision = [...faction.decisionLog]
    .sort((left, right) => right.occurredAtUtc.localeCompare(left.occurredAtUtc))[0];
  return {
    kind: "faction",
    id: faction.id,
    label: faction.label,
    stateLines: [
      `Posture ${faction.doctrine.strategicPosture} · ${faction.doctrine.militaryPosture}`,
      `Campaigns ${activeCampaigns.length} · Fronts ${activeTheaters.length} · Wars ${activeWars}`,
      `Commit ${economic.militaryShipCount}/${economic.targetMilitaryShipCount} mil · ${economic.minerShipCount}/${economic.targetMinerShipCount} min`,
      `Reserve ${strategicState.budget.reservedMilitaryAssets} mil · ${strategicState.budget.reservedLogisticsAssets} log`,
      `Bottleneck ${economic.industrialBottleneckItemId ?? "none"} · Contested ${contestedSystems}${latestDecision ? ` · ${latestDecision.kind}` : ""}`,
    ],
    priorities: [
      ...(leadCampaign ? [{ label: leadCampaign.kind, value: leadCampaign.priority.toFixed(0) }] : []),
      ...(leadTheater ? [{ label: leadTheater.kind, value: leadTheater.priority.toFixed(0) }] : []),
    ],
  };
}

function buildProgressBar(label: string, progress: number): HudProgressBar {
  return {
    label,
    valueLabel: `${Math.round(progress * 100)}%`,
    progress: Number((progress * 100).toFixed(1)),
  };
}

function buildStationCard(station: StationSnapshot, isSelected: boolean): OpsStationCardState {
  const cargo = station.inventory.reduce((sum, entry) => sum + entry.amount, 0);
  return {
    kind: "station",
    id: station.id,
    label: station.label,
    badge: station.category,
    selected: isSelected,
    lines: [
      station.systemId,
      `Docked ${station.dockedShips} / ${station.dockingPads}`,
      `Cargo ${cargo.toFixed(0)} · Pop ${station.population.toFixed(0)}`,
      `Modules ${station.installedModules.length}`,
    ],
    processes: station.currentProcesses.map((process) => buildProgressBar(process.label, process.progress)),
  };
}

function buildShipCard(
  world: WorldState,
  ship: WorldState["ships"] extends Map<string, infer Ship> ? Ship : never,
  isSelected: boolean,
  isFollowed: boolean,
): OpsShipCardState {
  const cargo = ship.inventory.reduce((sum, entry) => sum + entry.amount, 0);
  const shipLocation = describeShipLocation(world, ship);
  const shipState = describeShipState(world, ship);
  const shipAction = describeShipCurrentAction(ship);
  const currentStep = ship.activePlan?.steps[ship.activePlan.currentStepIndex];
  const topOrder = [...ship.orderQueue]
    .sort((left, right) => right.priority - left.priority || left.createdAtUtc.localeCompare(right.createdAtUtc))[0];

  return {
    kind: "ship",
    id: ship.id,
    label: ship.name,
    badge: ship.type,
    selected: isSelected,
    followed: isFollowed,
    locationLines: [shipLocation.system, ...(shipLocation.local ? [shipLocation.local] : [])],
    lines: [
      `Cargo ${cargo.toFixed(0)}`,
      `State ${shipState}`,
    ],
    action: shipAction ? buildProgressBar(shipAction.label, shipAction.progress) : undefined,
    aiLines: [
      `Assignment ${ship.assignment?.kind ?? "unassigned"}`,
      `Behavior ${getShipBehaviorLabel(ship.defaultBehavior.kind)}`,
      `Plan ${ship.activePlan ? `${ship.activePlan.kind}${currentStep ? ` · ${currentStep.kind}` : ""}` : "none"}`,
      `Orders ${topOrder ? `${getShipOrderLabel(topOrder.kind)} +${Math.max(0, ship.orderQueue.length - 1)}` : "none"}`,
    ],
  };
}

export function buildOpsStripState(
  world: WorldState | undefined,
  selectedItems: Selectable[],
  cameraMode: CameraMode,
  cameraTargetShipId?: string,
  povLevel?: PovLevel,
  activeSystemId?: string,
): OpsStripState {
  if (!world) {
    return {
      factions: [],
      stations: [],
      ships: [],
    };
  }

  const isSystemFiltered = povLevel !== "galaxy" && activeSystemId != null;

  const factions = [...world.factions.values()]
    .sort((left, right) => left.label.localeCompare(right.label))
    .map((faction) => buildFactionCard(world, faction));

  const stations = [...world.stations.values()]
    .filter((station) => !isSystemFiltered || station.systemId === activeSystemId)
    .sort((left, right) => left.label.localeCompare(right.label))
    .map((station) => buildStationCard(
      station,
      selectedItems.length === 1 && selectedItems[0].kind === "station" && selectedItems[0].id === station.id,
    ));

  const ships = [...world.ships.values()]
    .filter((ship) => !isSystemFiltered || ship.systemId === activeSystemId)
    .sort((left, right) => left.name.localeCompare(right.name))
    .map((ship) => buildShipCard(
      world,
      ship,
      selectedItems.length === 1 && selectedItems[0].kind === "ship" && selectedItems[0].id === ship.id,
      cameraMode === "follow" && cameraTargetShipId === ship.id,
    ));

  return { factions, stations, ships };
}
