<script setup lang="ts">
import { computed, onMounted, reactive, ref, watch } from "vue";
import { storeToRefs } from "pinia";
import {
  createPlayerOrganization,
  deletePlayerDirective,
  deletePlayerOrganization,
  enqueueShipOrder,
  fetchPlayerFaction,
  updatePlayerStrategicIntent,
  updateShipDefaultBehavior,
  upsertPlayerAssignment,
  upsertPlayerAutomationPolicy,
  upsertPlayerDirective,
  upsertPlayerPolicy,
} from "../../api";
import { getShipBehaviorLabel, getShipOrderLabel } from "../../shipAutomationPresentation";
import type { PlayerFactionSnapshot } from "../../contractsPlayerFaction";
import { useGmStore } from "../../ui/stores/gmStore";
import { useAuthStore } from "../../ui/stores/authStore";
import { usePlayerFactionStore } from "../../ui/stores/playerFactionStore";
import { useShipAutomationCatalogStore } from "../../ui/stores/shipAutomationCatalogStore";
import { useViewerSelectionStore } from "../../ui/stores/viewerSelection";

const gmStore = useGmStore();
const authStore = useAuthStore();
const playerStore = usePlayerFactionStore();
const automationStore = useShipAutomationCatalogStore();
const selectionStore = useViewerSelectionStore();
const { selectedEntityId, selectedEntityKind } = storeToRefs(selectionStore);
const { playerFaction } = storeToRefs(playerStore);
const { session } = storeToRefs(authStore);

const statusMessage = ref("");
const errorMessage = ref("");
const busy = ref(false);

const player = computed(() => playerFaction.value);
const selectedShip = computed(() => {
  if (selectedEntityKind.value !== "ship" || !selectedEntityId.value || !player.value?.assetRegistry.shipIds.includes(selectedEntityId.value)) {
    return null;
  }
  return gmStore.ships.find((ship) => ship.id === selectedEntityId.value) ?? null;
});
const selectedStation = computed(() => {
  if (selectedEntityKind.value !== "station" || !selectedEntityId.value || !player.value?.assetRegistry.stationIds.includes(selectedEntityId.value)) {
    return null;
  }
  return gmStore.stations.find((station) => station.id === selectedEntityId.value) ?? null;
});
const selectedAssignment = computed(() => {
  const assetKind = selectedShip.value ? "ship" : selectedStation.value ? "station" : null;
  const assetId = selectedShip.value?.id ?? selectedStation.value?.id;
  if (!assetKind || !assetId || !player.value) {
    return null;
  }
  return player.value.assignments.find((assignment) => assignment.assetKind === assetKind && assignment.assetId === assetId) ?? null;
});

const organizations = computed(() => {
  if (!player.value) {
    return [];
  }

  return [
    ...player.value.fleets.map((entry) => ({ kind: "fleet", id: entry.id, label: entry.label, summary: `${entry.role} · ${entry.assetIds.length} ships`, updatedAtUtc: entry.updatedAtUtc })),
    ...player.value.taskForces.map((entry) => ({ kind: "task-force", id: entry.id, label: entry.label, summary: `${entry.role} · ${entry.assetIds.length} ships`, updatedAtUtc: entry.updatedAtUtc })),
    ...player.value.stationGroups.map((entry) => ({ kind: "station-group", id: entry.id, label: entry.label, summary: `${entry.role} · ${entry.stationIds.length} stations`, updatedAtUtc: entry.updatedAtUtc })),
    ...player.value.economicRegions.map((entry) => ({ kind: "economic-region", id: entry.id, label: entry.label, summary: `${entry.role} · ${entry.systemIds.length} systems`, updatedAtUtc: entry.updatedAtUtc })),
    ...player.value.fronts.map((entry) => ({ kind: "front", id: entry.id, label: entry.label, summary: `${entry.posture} · P${Math.round(entry.priority)}`, updatedAtUtc: entry.updatedAtUtc })),
    ...player.value.reserves.map((entry) => ({ kind: "reserve", id: entry.id, label: entry.label, summary: `${entry.reserveKind} · ${entry.assetIds.length} ships`, updatedAtUtc: entry.updatedAtUtc })),
  ].sort((left, right) => left.kind.localeCompare(right.kind) || left.label.localeCompare(right.label));
});

const selectedOrganizationDetails = computed(() => {
  if (!player.value || !playerStore.selectedOrganizationId) {
    return null;
  }
  const id = playerStore.selectedOrganizationId;
  return player.value.fleets.find((entry) => entry.id === id)
    ?? player.value.taskForces.find((entry) => entry.id === id)
    ?? player.value.stationGroups.find((entry) => entry.id === id)
    ?? player.value.economicRegions.find((entry) => entry.id === id)
    ?? player.value.fronts.find((entry) => entry.id === id)
    ?? player.value.reserves.find((entry) => entry.id === id)
    ?? null;
});

const selectedOrganizationSummary = computed(() => {
  const entry = selectedOrganizationDetails.value;
  if (!entry) {
    return [];
  }

  const lines: string[] = [];
  if ("role" in entry) {
    lines.push(`Role ${entry.role}`);
  }
  if ("posture" in entry) {
    lines.push(`Posture ${entry.posture}`);
  }
  if ("commanderId" in entry && entry.commanderId) {
    lines.push(`Commander ${entry.commanderId}`);
  }
  if ("frontId" in entry && entry.frontId) {
    lines.push(`Front ${entry.frontId}`);
  }
  if ("fleetId" in entry && entry.fleetId) {
    lines.push(`Fleet ${entry.fleetId}`);
  }
  if ("economicRegionId" in entry && entry.economicRegionId) {
    lines.push(`Region ${entry.economicRegionId}`);
  }
  if ("sharedEconomicRegionId" in entry && entry.sharedEconomicRegionId) {
    lines.push(`Shared Region ${entry.sharedEconomicRegionId}`);
  }
  if ("sharedFrontLineId" in entry && entry.sharedFrontLineId) {
    lines.push(`Shared Front ${entry.sharedFrontLineId}`);
  }
  if ("homeSystemId" in entry && entry.homeSystemId) {
    lines.push(`Home ${entry.homeSystemId}`);
  }
  if ("assetIds" in entry) {
    lines.push(`Assets ${entry.assetIds.length}`);
  }
  if ("stationIds" in entry) {
    lines.push(`Stations ${entry.stationIds.length}`);
  }
  if ("systemIds" in entry) {
    lines.push(`Systems ${entry.systemIds.length}`);
  }
  if ("directiveIds" in entry) {
    lines.push(`Directives ${entry.directiveIds.length}`);
  }
  return lines;
});

const behaviorOptions = computed(() =>
  (automationStore.catalog?.behaviors ?? [])
    .filter((entry) => entry.supportStatus !== "InternalOnly")
    .map((entry) => entry.id),
);

onMounted(async () => {
  await automationStore.load();
  await loadPlayerSnapshotIfNeeded();
});

const orderOptions = computed(() =>
  (automationStore.catalog?.orders ?? [])
    .filter((entry) => entry.supportStatus !== "InternalOnly")
    .map((entry) => entry.id),
);

const orgForm = reactive({
  kind: "fleet",
  label: "",
  parentOrganizationId: "",
  frontId: "",
  homeSystemId: "",
  homeStationId: "",
  policyId: "",
  automationPolicyId: "",
  reinforcementPolicyId: "",
  targetFactionId: "",
  priority: 50,
  role: "",
  reserveKind: "military",
  notes: "",
});

const directiveForm = reactive({
  label: "",
  kind: "delegated-control",
  scopeKind: "asset",
  scopeId: "",
  behaviorKind: "hold-position",
  useOrders: false,
  stagingOrderKind: "",
  targetEntityId: "",
  targetSystemId: "",
  itemId: "",
  priority: 60,
  radius: 24,
  waitSeconds: 3,
  maxSystemRange: 0,
  knownStationsOnly: false,
  policyId: "",
  automationPolicyId: "",
  notes: "",
});

const assignmentForm = reactive({
  fleetId: "",
  taskForceId: "",
  stationGroupId: "",
  economicRegionId: "",
  frontId: "",
  reserveId: "",
  directiveId: "",
  policyId: "",
  automationPolicyId: "",
  role: "line",
});

const strategyForm = reactive({
  strategicPosture: "balanced",
  economicPosture: "delegated",
  militaryPosture: "layered-defense",
  logisticsPosture: "stable",
  desiredReserveRatio: 0.2,
  allowDelegatedCombatAutomation: true,
  allowDelegatedEconomicAutomation: true,
  notes: "",
});

const policyForm = reactive({
  label: "Core Empire Policy",
  allowDelegatedCombat: true,
  allowDelegatedTrade: true,
  reserveCreditsRatio: 0.2,
  reserveMilitaryRatio: 0.2,
  tradeAccessPolicy: "owner-and-allies",
  dockingAccessPolicy: "owner-and-allies",
  constructionAccessPolicy: "owner-only",
  operationalRangePolicy: "unrestricted",
  combatEngagementPolicy: "defensive",
  avoidHostileSystems: true,
  fleeHullRatio: 0.35,
  blacklistedSystemIds: "",
  notes: "",
});

const automationForm = reactive({
  label: "Core Automation",
  enabled: true,
  behaviorKind: "idle",
  useOrders: false,
  stagingOrderKind: "",
  maxSystemRange: 0,
  knownStationsOnly: false,
  radius: 24,
  waitSeconds: 3,
  preferredItemId: "",
  notes: "",
});

const behaviorForm = reactive({
  kind: "hold-position",
  homeSystemId: "",
  areaSystemId: "",
  targetEntityId: "",
  itemId: "",
  preferredNodeId: "",
  preferredConstructionSiteId: "",
  preferredModuleId: "",
  waitSeconds: 3,
  radius: 18,
  maxSystemRange: 0,
  knownStationsOnly: false,
});

const orderForm = reactive({
  kind: "hold-position",
  priority: 100,
  interruptCurrentPlan: true,
  label: "",
  targetEntityId: "",
  targetSystemId: "",
  itemId: "",
  nodeId: "",
  constructionSiteId: "",
  moduleId: "",
  waitSeconds: 3,
  radius: 18,
  maxSystemRange: 0,
  knownStationsOnly: false,
});

watch(player, (value) => {
  if (!value) {
    return;
  }

  strategyForm.strategicPosture = value.strategicIntent.strategicPosture;
  strategyForm.economicPosture = value.strategicIntent.economicPosture;
  strategyForm.militaryPosture = value.strategicIntent.militaryPosture;
  strategyForm.logisticsPosture = value.strategicIntent.logisticsPosture;
  strategyForm.desiredReserveRatio = value.strategicIntent.desiredReserveRatio;
  strategyForm.allowDelegatedCombatAutomation = value.strategicIntent.allowDelegatedCombatAutomation;
  strategyForm.allowDelegatedEconomicAutomation = value.strategicIntent.allowDelegatedEconomicAutomation;
  strategyForm.notes = value.strategicIntent.notes ?? "";

  const corePolicy = value.policies.find((entry) => entry.id === "player-core-policy") ?? value.policies[0];
  if (corePolicy) {
    policyForm.label = corePolicy.label;
    policyForm.allowDelegatedCombat = corePolicy.allowDelegatedCombat;
    policyForm.allowDelegatedTrade = corePolicy.allowDelegatedTrade;
    policyForm.reserveCreditsRatio = corePolicy.reserveCreditsRatio;
    policyForm.reserveMilitaryRatio = corePolicy.reserveMilitaryRatio;
    policyForm.tradeAccessPolicy = corePolicy.tradeAccessPolicy;
    policyForm.dockingAccessPolicy = corePolicy.dockingAccessPolicy;
    policyForm.constructionAccessPolicy = corePolicy.constructionAccessPolicy;
    policyForm.operationalRangePolicy = corePolicy.operationalRangePolicy;
    policyForm.combatEngagementPolicy = corePolicy.combatEngagementPolicy;
    policyForm.avoidHostileSystems = corePolicy.avoidHostileSystems;
    policyForm.fleeHullRatio = corePolicy.fleeHullRatio;
    policyForm.blacklistedSystemIds = corePolicy.blacklistedSystemIds.join(", ");
    policyForm.notes = corePolicy.notes ?? "";
  }

  const coreAutomation = value.automationPolicies.find((entry) => entry.id === "player-core-automation") ?? value.automationPolicies[0];
  if (coreAutomation) {
    automationForm.label = coreAutomation.label;
    automationForm.enabled = coreAutomation.enabled;
    automationForm.behaviorKind = coreAutomation.behaviorKind;
    automationForm.useOrders = coreAutomation.useOrders;
    automationForm.stagingOrderKind = coreAutomation.stagingOrderKind ?? "";
    automationForm.maxSystemRange = coreAutomation.maxSystemRange;
    automationForm.knownStationsOnly = coreAutomation.knownStationsOnly;
    automationForm.radius = coreAutomation.radius;
    automationForm.waitSeconds = coreAutomation.waitSeconds;
    automationForm.preferredItemId = coreAutomation.preferredItemId ?? "";
    automationForm.notes = coreAutomation.notes ?? "";
  }
}, { immediate: true });

watch(session, async (value) => {
  if (!value) {
    playerStore.setPlayerFaction(null);
    return;
  }

  await loadPlayerSnapshotIfNeeded();
});

watch(selectedShip, (ship) => {
  if (!ship) {
    return;
  }

  behaviorForm.kind = ship.defaultBehavior.kind;
  behaviorForm.homeSystemId = ship.defaultBehavior.homeSystemId ?? ship.systemId;
  behaviorForm.areaSystemId = ship.defaultBehavior.areaSystemId ?? ship.systemId;
  behaviorForm.targetEntityId = ship.defaultBehavior.targetEntityId ?? "";
  behaviorForm.itemId = ship.defaultBehavior.itemId ?? "";
  behaviorForm.preferredNodeId = ship.defaultBehavior.preferredNodeId ?? "";
  behaviorForm.preferredConstructionSiteId = ship.defaultBehavior.preferredConstructionSiteId ?? "";
  behaviorForm.preferredModuleId = ship.defaultBehavior.preferredModuleId ?? "";
  behaviorForm.waitSeconds = ship.defaultBehavior.waitSeconds;
  behaviorForm.radius = ship.defaultBehavior.radius;
  behaviorForm.maxSystemRange = ship.defaultBehavior.maxSystemRange;
  behaviorForm.knownStationsOnly = ship.defaultBehavior.knownStationsOnly;
  if (!directiveForm.scopeId) {
    directiveForm.scopeId = ship.id;
  }
  if (directiveForm.scopeKind === "asset") {
    directiveForm.scopeKind = "ship";
  }
}, { immediate: true });

watch(selectedStation, (station) => {
  if (!station) {
    return;
  }
  if (!directiveForm.scopeId) {
    directiveForm.scopeId = station.id;
  }
  if (directiveForm.scopeKind === "asset") {
    directiveForm.scopeKind = "station";
  }
}, { immediate: true });

watch(selectedAssignment, (assignment) => {
  assignmentForm.fleetId = assignment?.fleetId ?? "";
  assignmentForm.taskForceId = assignment?.taskForceId ?? "";
  assignmentForm.stationGroupId = assignment?.stationGroupId ?? "";
  assignmentForm.economicRegionId = assignment?.economicRegionId ?? "";
  assignmentForm.frontId = assignment?.frontId ?? "";
  assignmentForm.reserveId = assignment?.reserveId ?? "";
  assignmentForm.directiveId = assignment?.directiveId ?? "";
  assignmentForm.policyId = assignment?.policyId ?? "";
  assignmentForm.automationPolicyId = assignment?.automationPolicyId ?? "";
  assignmentForm.role = assignment?.role ?? "line";
}, { immediate: true });

function titleCase(value: string | null | undefined) {
  if (!value) {
    return "—";
  }
  return value
    .replace(/([a-z])([A-Z])/g, "$1 $2")
    .replace(/[-_]+/g, " ")
    .replace(/\s+/g, " ")
    .trim()
    .replace(/\b\w/g, (character) => character.toUpperCase());
}

function formatDate(value: string | null | undefined) {
  if (!value) {
    return "—";
  }
  return new Date(value).toLocaleString();
}

function setPlayerSnapshot(snapshot: PlayerFactionSnapshot) {
  playerStore.setPlayerFaction(snapshot);
}

async function loadPlayerSnapshotIfNeeded() {
  if (!authStore.isAuthenticated || playerStore.playerFaction) {
    return;
  }

  try {
    setPlayerSnapshot(await fetchPlayerFaction());
  } catch {
    // Player domain may not exist yet for the current world; leave the panel empty.
  }
}

async function runAction(action: () => Promise<void>, successMessage: string) {
  busy.value = true;
  errorMessage.value = "";
  statusMessage.value = "";
  try {
    await action();
    statusMessage.value = successMessage;
  } catch (error) {
    errorMessage.value = error instanceof Error ? error.message : "Request failed.";
  } finally {
    busy.value = false;
  }
}

async function submitOrganization() {
  await runAction(async () => {
    const snapshot = await createPlayerOrganization({
      kind: orgForm.kind,
      label: orgForm.label,
      parentOrganizationId: orgForm.parentOrganizationId || null,
      frontId: orgForm.frontId || null,
      homeSystemId: orgForm.homeSystemId || null,
      homeStationId: orgForm.homeStationId || null,
      policyId: orgForm.policyId || null,
      automationPolicyId: orgForm.automationPolicyId || null,
      reinforcementPolicyId: orgForm.reinforcementPolicyId || null,
      targetFactionId: orgForm.targetFactionId || null,
      priority: Number.isFinite(orgForm.priority) ? orgForm.priority : null,
      role: orgForm.role || null,
      reserveKind: orgForm.reserveKind || null,
      systemIds: [],
      focusItemIds: [],
      notes: orgForm.notes || null,
    });
    setPlayerSnapshot(snapshot);
    orgForm.label = "";
    orgForm.role = "";
    orgForm.notes = "";
  }, "Organization created.");
}

async function removeOrganization(organizationId: string) {
  await runAction(async () => {
    setPlayerSnapshot(await deletePlayerOrganization(organizationId));
  }, "Organization removed.");
}

async function submitDirective() {
  await runAction(async () => {
    const snapshot = await upsertPlayerDirective({
      label: directiveForm.label,
      kind: directiveForm.kind,
      scopeKind: directiveForm.scopeKind,
      scopeId: directiveForm.scopeId,
      behaviorKind: directiveForm.behaviorKind,
      useOrders: directiveForm.useOrders,
      stagingOrderKind: directiveForm.stagingOrderKind || null,
      targetEntityId: directiveForm.targetEntityId || null,
      targetSystemId: directiveForm.targetSystemId || null,
      targetPosition: null,
      homeSystemId: null,
      homeStationId: null,
      sourceStationId: null,
      destinationStationId: null,
      itemId: directiveForm.itemId || null,
      preferredNodeId: null,
      preferredConstructionSiteId: null,
      preferredModuleId: null,
      priority: directiveForm.priority,
      radius: directiveForm.radius,
      waitSeconds: directiveForm.waitSeconds,
      maxSystemRange: directiveForm.maxSystemRange,
      knownStationsOnly: directiveForm.knownStationsOnly,
      patrolPoints: [],
      repeatOrders: [],
      policyId: directiveForm.policyId || null,
      automationPolicyId: directiveForm.automationPolicyId || null,
      notes: directiveForm.notes || null,
    });
    setPlayerSnapshot(snapshot);
    directiveForm.label = "";
    directiveForm.notes = "";
  }, "Directive saved.");
}

async function removeDirective(directiveId: string) {
  await runAction(async () => {
    setPlayerSnapshot(await deletePlayerDirective(directiveId));
  }, "Directive removed.");
}

async function submitAssignment() {
  const asset = selectedShip.value ?? selectedStation.value;
  if (!asset) {
    errorMessage.value = "Select a player-owned ship or station first.";
    return;
  }

  await runAction(async () => {
    const snapshot = await upsertPlayerAssignment(asset.id, {
      assetKind: selectedShip.value ? "ship" : "station",
      assetId: asset.id,
      fleetId: assignmentForm.fleetId || null,
      taskForceId: assignmentForm.taskForceId || null,
      stationGroupId: assignmentForm.stationGroupId || null,
      economicRegionId: assignmentForm.economicRegionId || null,
      frontId: assignmentForm.frontId || null,
      reserveId: assignmentForm.reserveId || null,
      directiveId: assignmentForm.directiveId || null,
      policyId: assignmentForm.policyId || null,
      automationPolicyId: assignmentForm.automationPolicyId || null,
      role: assignmentForm.role,
      clearConflicts: true,
    });
    setPlayerSnapshot(snapshot);
  }, "Assignment saved.");
}

async function submitStrategicIntent() {
  await runAction(async () => {
    setPlayerSnapshot(await updatePlayerStrategicIntent({
      strategicPosture: strategyForm.strategicPosture,
      economicPosture: strategyForm.economicPosture,
      militaryPosture: strategyForm.militaryPosture,
      logisticsPosture: strategyForm.logisticsPosture,
      desiredReserveRatio: strategyForm.desiredReserveRatio,
      allowDelegatedCombatAutomation: strategyForm.allowDelegatedCombatAutomation,
      allowDelegatedEconomicAutomation: strategyForm.allowDelegatedEconomicAutomation,
      notes: strategyForm.notes || null,
    }));
  }, "Strategic intent updated.");
}

async function submitCorePolicy() {
  await runAction(async () => {
    setPlayerSnapshot(await upsertPlayerPolicy({
      label: policyForm.label,
      scopeKind: "player-faction",
      scopeId: player.value?.id ?? null,
      policySetId: player.value?.policies.find((entry) => entry.id === "player-core-policy")?.policySetId ?? null,
      allowDelegatedCombat: policyForm.allowDelegatedCombat,
      allowDelegatedTrade: policyForm.allowDelegatedTrade,
      reserveCreditsRatio: policyForm.reserveCreditsRatio,
      reserveMilitaryRatio: policyForm.reserveMilitaryRatio,
      notes: policyForm.notes || null,
      tradeAccessPolicy: policyForm.tradeAccessPolicy,
      dockingAccessPolicy: policyForm.dockingAccessPolicy,
      constructionAccessPolicy: policyForm.constructionAccessPolicy,
      operationalRangePolicy: policyForm.operationalRangePolicy,
      combatEngagementPolicy: policyForm.combatEngagementPolicy,
      avoidHostileSystems: policyForm.avoidHostileSystems,
      fleeHullRatio: policyForm.fleeHullRatio,
      blacklistedSystemIds: policyForm.blacklistedSystemIds.split(",").map((entry) => entry.trim()).filter(Boolean),
    }, "player-core-policy"));
  }, "Core policy updated.");
}

async function submitCoreAutomation() {
  await runAction(async () => {
    setPlayerSnapshot(await upsertPlayerAutomationPolicy({
      label: automationForm.label,
      scopeKind: "player-faction",
      scopeId: player.value?.id ?? null,
      enabled: automationForm.enabled,
      behaviorKind: automationForm.behaviorKind,
      useOrders: automationForm.useOrders,
      stagingOrderKind: automationForm.stagingOrderKind || null,
      maxSystemRange: automationForm.maxSystemRange,
      knownStationsOnly: automationForm.knownStationsOnly,
      radius: automationForm.radius,
      waitSeconds: automationForm.waitSeconds,
      preferredItemId: automationForm.preferredItemId || null,
      notes: automationForm.notes || null,
      repeatOrders: [],
    }, "player-core-automation"));
  }, "Core automation updated.");
}

async function submitDirectBehavior() {
  if (!selectedShip.value) {
    errorMessage.value = "Select a player-owned ship first.";
    return;
  }

  const selected = selectedShip.value;
  await runAction(async () => {
    const ship = await updateShipDefaultBehavior(selected.id, {
      kind: behaviorForm.kind,
      homeSystemId: behaviorForm.homeSystemId || selected.systemId || null,
      homeStationId: null,
      areaSystemId: behaviorForm.areaSystemId || null,
      targetEntityId: behaviorForm.targetEntityId || null,
      itemId: behaviorForm.itemId || null,
      preferredNodeId: behaviorForm.preferredNodeId || null,
      preferredConstructionSiteId: behaviorForm.preferredConstructionSiteId || null,
      preferredModuleId: behaviorForm.preferredModuleId || null,
      targetPosition: null,
      waitSeconds: behaviorForm.waitSeconds,
      radius: behaviorForm.radius,
      maxSystemRange: behaviorForm.maxSystemRange,
      knownStationsOnly: behaviorForm.knownStationsOnly,
      patrolPoints: [],
      repeatOrders: [],
    });
    gmStore.upsertShip(ship);
  }, "Ship behavior updated.");
}

async function submitDirectOrder() {
  if (!selectedShip.value) {
    errorMessage.value = "Select a player-owned ship first.";
    return;
  }

  const selected = selectedShip.value;
  await runAction(async () => {
    const ship = await enqueueShipOrder(selected.id, {
      kind: orderForm.kind,
      priority: orderForm.priority,
      interruptCurrentPlan: orderForm.interruptCurrentPlan,
      label: orderForm.label || null,
      targetEntityId: orderForm.targetEntityId || null,
      targetSystemId: orderForm.targetSystemId || null,
      targetPosition: null,
      sourceStationId: null,
      destinationStationId: null,
      itemId: orderForm.itemId || null,
      nodeId: orderForm.nodeId || null,
      constructionSiteId: orderForm.constructionSiteId || null,
      moduleId: orderForm.moduleId || null,
      waitSeconds: orderForm.waitSeconds,
      radius: orderForm.radius,
      maxSystemRange: orderForm.maxSystemRange,
      knownStationsOnly: orderForm.knownStationsOnly,
    });
    gmStore.upsertShip(ship);
  }, "Ship order queued.");
}
</script>

<template>
  <div class="player-panel" v-if="player">
    <div class="player-banner">
      <div>
        <div class="player-kicker">Player Faction</div>
        <h3>{{ player.label }}</h3>
        <p>{{ player.sovereignFactionId }} · {{ titleCase(player.strategicIntent.strategicPosture) }} / {{ titleCase(player.strategicIntent.economicPosture) }} / {{ titleCase(player.strategicIntent.militaryPosture) }}</p>
      </div>
      <div class="player-banner-metrics">
        <div><strong>{{ player.assetRegistry.shipIds.length }}</strong><span>Ships</span></div>
        <div><strong>{{ player.assetRegistry.stationIds.length }}</strong><span>Stations</span></div>
        <div><strong>{{ organizations.length }}</strong><span>Groups</span></div>
        <div><strong>{{ player.alerts.length }}</strong><span>Alerts</span></div>
      </div>
    </div>

    <div v-if="statusMessage" class="player-message player-message--ok">{{ statusMessage }}</div>
    <div v-if="errorMessage" class="player-message player-message--error">{{ errorMessage }}</div>

    <div class="player-grid">
      <section class="player-section">
        <h4>Selected Asset Control</h4>
        <div v-if="selectedShip || selectedStation" class="player-card-list">
          <div class="player-card">
            <strong>{{ selectedShip?.name ?? selectedStation?.label }}</strong>
            <span>{{ selectedShip ? "Ship" : "Station" }} · {{ selectedShip?.systemId ?? selectedStation?.systemId }}</span>
            <span v-if="selectedAssignment">Assignment {{ selectedAssignment.role }} · {{ selectedAssignment.directiveId ?? "no directive" }}</span>
            <span v-else>No player assignment</span>
          </div>
          <div v-if="selectedShip" class="player-card">
            <strong>Behavior</strong>
            <span>{{ getShipBehaviorLabel(selectedShip.defaultBehavior.kind) }}</span>
            <span>Orders {{ selectedShip.orderQueue.length }} · Plan {{ selectedShip.activePlan?.kind ?? "none" }}</span>
            <span>Command {{ titleCase(selectedShip.controlSourceKind) }}<template v-if="selectedShip.controlReason"> · {{ selectedShip.controlReason }}</template></span>
            <span v-if="selectedShip.lastReplanReason">Replan {{ selectedShip.lastReplanReason }}</span>
            <span v-if="selectedShip.lastAccessFailureReason">Access {{ selectedShip.lastAccessFailureReason }}</span>
          </div>
        </div>
        <p v-else class="player-empty">Select a player-owned ship or station to configure it.</p>

        <form v-if="selectedShip" class="player-form" @submit.prevent="submitDirectBehavior">
          <h5>Direct Ship Behavior</h5>
          <label><span>Behavior</span><select v-model="behaviorForm.kind"><option v-for="option in behaviorOptions" :key="option" :value="option">{{ getShipBehaviorLabel(option) }}</option></select></label>
          <label><span>Home System</span><input v-model="behaviorForm.homeSystemId" type="text"></label>
          <label><span>Area System</span><input v-model="behaviorForm.areaSystemId" type="text"></label>
          <label><span>Target Entity</span><input v-model="behaviorForm.targetEntityId" type="text"></label>
          <label><span>Item</span><input v-model="behaviorForm.itemId" type="text"></label>
          <label><span>Preferred Node</span><input v-model="behaviorForm.preferredNodeId" type="text"></label>
          <label><span>Construction Site</span><input v-model="behaviorForm.preferredConstructionSiteId" type="text"></label>
          <label><span>Module</span><input v-model="behaviorForm.preferredModuleId" type="text"></label>
          <label><span>Radius</span><input v-model.number="behaviorForm.radius" type="number" min="0" step="1"></label>
          <label><span>Wait Seconds</span><input v-model.number="behaviorForm.waitSeconds" type="number" min="0" step="1"></label>
          <label><span>System Range</span><input v-model.number="behaviorForm.maxSystemRange" type="number" min="0" step="1"></label>
          <label class="player-check"><input v-model="behaviorForm.knownStationsOnly" type="checkbox"><span>Known stations only</span></label>
          <button type="submit" :disabled="busy">Apply Behavior</button>
        </form>

        <form v-if="selectedShip" class="player-form" @submit.prevent="submitDirectOrder">
          <h5>Direct Ship Order</h5>
          <label><span>Order</span><select v-model="orderForm.kind"><option v-for="option in orderOptions" :key="option" :value="option">{{ getShipOrderLabel(option) }}</option></select></label>
          <label><span>Label</span><input v-model="orderForm.label" type="text"></label>
          <label><span>Target System</span><input v-model="orderForm.targetSystemId" type="text"></label>
          <label><span>Target Entity</span><input v-model="orderForm.targetEntityId" type="text"></label>
          <label><span>Item</span><input v-model="orderForm.itemId" type="text"></label>
          <label><span>Node</span><input v-model="orderForm.nodeId" type="text"></label>
          <label><span>Construction Site</span><input v-model="orderForm.constructionSiteId" type="text"></label>
          <label><span>Module</span><input v-model="orderForm.moduleId" type="text"></label>
          <label><span>Priority</span><input v-model.number="orderForm.priority" type="number" min="0" step="1"></label>
          <label><span>Radius</span><input v-model.number="orderForm.radius" type="number" min="0" step="1"></label>
          <label><span>Wait Seconds</span><input v-model.number="orderForm.waitSeconds" type="number" min="0" step="1"></label>
          <label><span>System Range</span><input v-model.number="orderForm.maxSystemRange" type="number" min="0" step="1"></label>
          <label class="player-check"><input v-model="orderForm.interruptCurrentPlan" type="checkbox"><span>Interrupt current plan</span></label>
          <button type="submit" :disabled="busy">Queue Order</button>
        </form>

        <form v-if="selectedShip || selectedStation" class="player-form" @submit.prevent="submitAssignment">
          <h5>Assignment</h5>
          <label><span>Fleet</span><select v-model="assignmentForm.fleetId"><option value="">—</option><option v-for="entry in player.fleets" :key="entry.id" :value="entry.id">{{ entry.label }}</option></select></label>
          <label><span>Task Force</span><select v-model="assignmentForm.taskForceId"><option value="">—</option><option v-for="entry in player.taskForces" :key="entry.id" :value="entry.id">{{ entry.label }}</option></select></label>
          <label><span>Station Group</span><select v-model="assignmentForm.stationGroupId"><option value="">—</option><option v-for="entry in player.stationGroups" :key="entry.id" :value="entry.id">{{ entry.label }}</option></select></label>
          <label><span>Region</span><select v-model="assignmentForm.economicRegionId"><option value="">—</option><option v-for="entry in player.economicRegions" :key="entry.id" :value="entry.id">{{ entry.label }}</option></select></label>
          <label><span>Front</span><select v-model="assignmentForm.frontId"><option value="">—</option><option v-for="entry in player.fronts" :key="entry.id" :value="entry.id">{{ entry.label }}</option></select></label>
          <label><span>Reserve</span><select v-model="assignmentForm.reserveId"><option value="">—</option><option v-for="entry in player.reserves" :key="entry.id" :value="entry.id">{{ entry.label }}</option></select></label>
          <label><span>Directive</span><select v-model="assignmentForm.directiveId"><option value="">—</option><option v-for="entry in player.directives" :key="entry.id" :value="entry.id">{{ entry.label }}</option></select></label>
          <label><span>Policy</span><select v-model="assignmentForm.policyId"><option value="">—</option><option v-for="entry in player.policies" :key="entry.id" :value="entry.id">{{ entry.label }}</option></select></label>
          <label><span>Automation</span><select v-model="assignmentForm.automationPolicyId"><option value="">—</option><option v-for="entry in player.automationPolicies" :key="entry.id" :value="entry.id">{{ entry.label }}</option></select></label>
          <label><span>Role</span><input v-model="assignmentForm.role" type="text"></label>
          <button type="submit" :disabled="busy">Save Assignment</button>
        </form>
      </section>

      <section class="player-section">
        <h4>Strategic Control</h4>
        <form class="player-form" @submit.prevent="submitStrategicIntent">
          <label><span>Strategic</span><input v-model="strategyForm.strategicPosture" type="text"></label>
          <label><span>Economic</span><input v-model="strategyForm.economicPosture" type="text"></label>
          <label><span>Military</span><input v-model="strategyForm.militaryPosture" type="text"></label>
          <label><span>Logistics</span><input v-model="strategyForm.logisticsPosture" type="text"></label>
          <label><span>Reserve Ratio</span><input v-model.number="strategyForm.desiredReserveRatio" type="number" min="0" max="1" step="0.05"></label>
          <label class="player-check"><input v-model="strategyForm.allowDelegatedCombatAutomation" type="checkbox"><span>Allow delegated combat automation</span></label>
          <label class="player-check"><input v-model="strategyForm.allowDelegatedEconomicAutomation" type="checkbox"><span>Allow delegated economic automation</span></label>
          <label class="player-full"><span>Notes</span><textarea v-model="strategyForm.notes" rows="2"></textarea></label>
          <button type="submit" :disabled="busy">Update Strategic Intent</button>
        </form>

        <form class="player-form" @submit.prevent="submitCorePolicy">
          <h5>Core Policy</h5>
          <label><span>Label</span><input v-model="policyForm.label" type="text"></label>
          <label><span>Trade Access</span><input v-model="policyForm.tradeAccessPolicy" type="text"></label>
          <label><span>Docking Access</span><input v-model="policyForm.dockingAccessPolicy" type="text"></label>
          <label><span>Construction Access</span><input v-model="policyForm.constructionAccessPolicy" type="text"></label>
          <label><span>Operational Range</span><input v-model="policyForm.operationalRangePolicy" type="text"></label>
          <label><span>Combat Policy</span><input v-model="policyForm.combatEngagementPolicy" type="text"></label>
          <label><span>Reserve Credits</span><input v-model.number="policyForm.reserveCreditsRatio" type="number" min="0" max="1" step="0.05"></label>
          <label><span>Reserve Military</span><input v-model.number="policyForm.reserveMilitaryRatio" type="number" min="0" max="1" step="0.05"></label>
          <label><span>Flee Hull Ratio</span><input v-model.number="policyForm.fleeHullRatio" type="number" min="0" max="1" step="0.05"></label>
          <label><span>Blacklisted Systems</span><input v-model="policyForm.blacklistedSystemIds" type="text" placeholder="sys-a, sys-b"></label>
          <label class="player-check"><input v-model="policyForm.allowDelegatedCombat" type="checkbox"><span>Allow delegated combat</span></label>
          <label class="player-check"><input v-model="policyForm.allowDelegatedTrade" type="checkbox"><span>Allow delegated trade</span></label>
          <label class="player-check"><input v-model="policyForm.avoidHostileSystems" type="checkbox"><span>Avoid hostile systems</span></label>
          <label class="player-full"><span>Notes</span><textarea v-model="policyForm.notes" rows="2"></textarea></label>
          <button type="submit" :disabled="busy">Update Core Policy</button>
        </form>

        <form class="player-form" @submit.prevent="submitCoreAutomation">
          <h5>Core Automation</h5>
          <label><span>Label</span><input v-model="automationForm.label" type="text"></label>
          <label><span>Behavior</span><select v-model="automationForm.behaviorKind"><option v-for="option in behaviorOptions" :key="option" :value="option">{{ getShipBehaviorLabel(option) }}</option></select></label>
          <label><span>Order Staging</span><input v-model="automationForm.stagingOrderKind" type="text"></label>
          <label><span>Preferred Item</span><input v-model="automationForm.preferredItemId" type="text"></label>
          <label><span>System Range</span><input v-model.number="automationForm.maxSystemRange" type="number" min="0" step="1"></label>
          <label><span>Radius</span><input v-model.number="automationForm.radius" type="number" min="0" step="1"></label>
          <label><span>Wait Seconds</span><input v-model.number="automationForm.waitSeconds" type="number" min="0" step="1"></label>
          <label class="player-check"><input v-model="automationForm.enabled" type="checkbox"><span>Enabled</span></label>
          <label class="player-check"><input v-model="automationForm.useOrders" type="checkbox"><span>Use staging orders</span></label>
          <label class="player-check"><input v-model="automationForm.knownStationsOnly" type="checkbox"><span>Known stations only</span></label>
          <label class="player-full"><span>Notes</span><textarea v-model="automationForm.notes" rows="2"></textarea></label>
          <button type="submit" :disabled="busy">Update Core Automation</button>
        </form>
      </section>

      <section class="player-section">
        <h4>Organization and Directives</h4>
        <form class="player-form" @submit.prevent="submitOrganization">
          <h5>Create Organization</h5>
          <label><span>Kind</span><select v-model="orgForm.kind"><option value="fleet">Fleet</option><option value="task-force">Task Force</option><option value="station-group">Station Group</option><option value="economic-region">Economic Region</option><option value="front">Front</option><option value="reserve">Reserve</option></select></label>
          <label><span>Label</span><input v-model="orgForm.label" type="text"></label>
          <label><span>Role / Posture</span><input v-model="orgForm.role" type="text"></label>
          <label><span>Parent Org</span><input v-model="orgForm.parentOrganizationId" type="text"></label>
          <label><span>Front</span><input v-model="orgForm.frontId" type="text"></label>
          <label><span>Home System</span><input v-model="orgForm.homeSystemId" type="text"></label>
          <label><span>Home Station</span><input v-model="orgForm.homeStationId" type="text"></label>
          <label><span>Target Faction</span><input v-model="orgForm.targetFactionId" type="text"></label>
          <label><span>Priority</span><input v-model.number="orgForm.priority" type="number" min="0" step="1"></label>
          <label><span>Reserve Kind</span><input v-model="orgForm.reserveKind" type="text"></label>
          <label class="player-full"><span>Notes</span><textarea v-model="orgForm.notes" rows="2"></textarea></label>
          <button type="submit" :disabled="busy || !orgForm.label">Create Organization</button>
        </form>

        <div class="player-list">
          <div class="player-list-header"><span>Organizations</span><span>{{ organizations.length }}</span></div>
          <button
            v-for="entry in organizations"
            :key="entry.id"
            type="button"
            class="player-list-item"
            :class="playerStore.selectedOrganizationId === entry.id ? 'player-list-item--active' : ''"
            @click="playerStore.selectOrganization(entry.id)"
          >
            <span><strong>{{ entry.label }}</strong><em>{{ titleCase(entry.kind) }}</em></span>
            <span>{{ entry.summary }}</span>
            <span class="player-actions"><small>{{ formatDate(entry.updatedAtUtc) }}</small><span class="player-link" @click.stop="removeOrganization(entry.id)">Delete</span></span>
          </button>
        </div>

        <div v-if="selectedOrganizationDetails" class="player-card">
          <strong>{{ selectedOrganizationDetails.label ?? playerStore.selectedOrganizationId }}</strong>
          <span v-for="line in selectedOrganizationSummary" :key="line">{{ line }}</span>
        </div>

        <form class="player-form" @submit.prevent="submitDirective">
          <h5>Create Directive</h5>
          <label><span>Label</span><input v-model="directiveForm.label" type="text"></label>
          <label><span>Kind</span><input v-model="directiveForm.kind" type="text"></label>
          <label><span>Scope Kind</span><input v-model="directiveForm.scopeKind" type="text"></label>
          <label><span>Scope Id</span><input v-model="directiveForm.scopeId" type="text" :placeholder="selectedEntityId ?? ''"></label>
          <label><span>Behavior</span><select v-model="directiveForm.behaviorKind"><option v-for="option in behaviorOptions" :key="option" :value="option">{{ getShipBehaviorLabel(option) }}</option></select></label>
          <label><span>Staging Order</span><input v-model="directiveForm.stagingOrderKind" type="text"></label>
          <label><span>Target System</span><input v-model="directiveForm.targetSystemId" type="text"></label>
          <label><span>Target Entity</span><input v-model="directiveForm.targetEntityId" type="text"></label>
          <label><span>Item</span><input v-model="directiveForm.itemId" type="text"></label>
          <label><span>Priority</span><input v-model.number="directiveForm.priority" type="number" min="0" step="1"></label>
          <label><span>Radius</span><input v-model.number="directiveForm.radius" type="number" min="0" step="1"></label>
          <label><span>Wait Seconds</span><input v-model.number="directiveForm.waitSeconds" type="number" min="0" step="1"></label>
          <label><span>System Range</span><input v-model.number="directiveForm.maxSystemRange" type="number" min="0" step="1"></label>
          <label class="player-check"><input v-model="directiveForm.useOrders" type="checkbox"><span>Use staging order</span></label>
          <label class="player-check"><input v-model="directiveForm.knownStationsOnly" type="checkbox"><span>Known stations only</span></label>
          <label class="player-full"><span>Notes</span><textarea v-model="directiveForm.notes" rows="2"></textarea></label>
          <button type="submit" :disabled="busy || !directiveForm.label || !directiveForm.scopeId">Save Directive</button>
        </form>

        <div class="player-list">
          <div class="player-list-header"><span>Directives</span><span>{{ player.directives.length }}</span></div>
          <button
            v-for="directive in player.directives"
            :key="directive.id"
            type="button"
            class="player-list-item"
            :class="playerStore.selectedDirectiveId === directive.id ? 'player-list-item--active' : ''"
            @click="playerStore.selectDirective(directive.id)"
          >
            <span><strong>{{ directive.label }}</strong><em>{{ titleCase(directive.scopeKind) }} / {{ directive.scopeId }}</em></span>
            <span>{{ titleCase(directive.behaviorKind) }} · {{ titleCase(directive.status) }}</span>
            <span class="player-actions"><small>{{ formatDate(directive.updatedAtUtc) }}</small><span class="player-link" @click.stop="removeDirective(directive.id)">Delete</span></span>
          </button>
        </div>
      </section>

      <section class="player-section">
        <h4>Observability</h4>
        <div class="player-list">
          <div class="player-list-header"><span>Alerts</span><span>{{ player.alerts.length }}</span></div>
          <div v-for="alert in player.alerts" :key="alert.id" class="player-list-item player-list-item--static">
            <span><strong>{{ titleCase(alert.kind) }}</strong><em>{{ titleCase(alert.severity) }}</em></span>
            <span>{{ alert.summary }}</span>
            <span><small>{{ formatDate(alert.createdAtUtc) }}</small></span>
          </div>
        </div>

        <div class="player-list">
          <div class="player-list-header"><span>Decision Log</span><span>{{ player.decisionLog.length }}</span></div>
          <div v-for="decision in player.decisionLog.slice(0, 12)" :key="decision.id" class="player-list-item player-list-item--static">
            <span><strong>{{ titleCase(decision.kind) }}</strong><em>{{ decision.relatedEntityKind ?? "—" }}</em></span>
            <span>{{ decision.summary }}</span>
            <span><small>{{ formatDate(decision.occurredAtUtc) }}</small></span>
          </div>
        </div>
      </section>
    </div>
  </div>

  <div v-else class="player-empty-state">
    Player faction state is not available.
  </div>
</template>

<style scoped>
.player-panel {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  padding: 0.75rem;
  color: rgba(226, 232, 240, 0.92);
}

.player-banner {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  border: 1px solid rgba(148, 163, 184, 0.2);
  background: linear-gradient(135deg, rgba(15, 23, 42, 0.96), rgba(12, 18, 31, 0.9));
  padding: 0.85rem 1rem;
}

.player-banner h3 {
  margin: 0;
  font-size: 1rem;
}

.player-banner p,
.player-kicker {
  margin: 0.2rem 0 0;
  font-size: 0.75rem;
  opacity: 0.75;
}

.player-kicker {
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: rgba(125, 211, 252, 0.88);
}

.player-banner-metrics {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.75rem;
  min-width: 20rem;
}

.player-banner-metrics div {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  font-size: 0.75rem;
}

.player-banner-metrics strong {
  font-size: 1.1rem;
}

.player-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1rem;
}

.player-section {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  border: 1px solid rgba(148, 163, 184, 0.16);
  background: rgba(15, 23, 42, 0.78);
  padding: 0.85rem;
}

.player-section h4,
.player-section h5 {
  margin: 0;
}

.player-form {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.55rem 0.75rem;
}

.player-form label {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  font-size: 0.72rem;
}

.player-form label span {
  opacity: 0.74;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.player-form input,
.player-form select,
.player-form textarea,
.player-form button {
  border: 1px solid rgba(148, 163, 184, 0.22);
  background: rgba(15, 23, 42, 0.94);
  color: inherit;
  padding: 0.45rem 0.55rem;
  font: inherit;
}

.player-form button {
  cursor: pointer;
  background: rgba(14, 116, 144, 0.24);
  font-weight: 600;
}

.player-form button:disabled {
  cursor: wait;
  opacity: 0.55;
}

.player-full,
.player-form button {
  grid-column: 1 / -1;
}

.player-check {
  flex-direction: row !important;
  align-items: center;
  gap: 0.45rem !important;
}

.player-check span {
  text-transform: none !important;
  letter-spacing: normal !important;
}

.player-list {
  display: flex;
  flex-direction: column;
  border: 1px solid rgba(148, 163, 184, 0.16);
}

.player-list-header,
.player-list-item {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, 0.7fr);
  gap: 0.75rem;
  padding: 0.5rem 0.65rem;
  font-size: 0.74rem;
}

.player-list-header {
  background: rgba(30, 41, 59, 0.72);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 0.65rem;
}

.player-list-item {
  border-top: 1px solid rgba(148, 163, 184, 0.08);
  background: transparent;
  color: inherit;
  text-align: left;
}

.player-list-item--active {
  background: rgba(8, 47, 73, 0.46);
}

.player-list-item--static {
  display: grid;
}

.player-list-item strong,
.player-card strong {
  display: block;
}

.player-list-item em,
.player-card span,
.player-actions small {
  display: block;
  font-style: normal;
  opacity: 0.72;
}

.player-actions {
  text-align: right;
}

.player-link {
  color: rgba(248, 113, 113, 0.92);
  cursor: pointer;
}

.player-card-list {
  display: grid;
  gap: 0.65rem;
}

.player-card {
  border: 1px solid rgba(148, 163, 184, 0.16);
  padding: 0.55rem 0.65rem;
  background: rgba(15, 23, 42, 0.52);
  font-size: 0.74rem;
}

.player-message {
  padding: 0.55rem 0.7rem;
  font-size: 0.76rem;
}

.player-message--ok {
  background: rgba(22, 163, 74, 0.16);
  border: 1px solid rgba(22, 163, 74, 0.3);
}

.player-message--error {
  background: rgba(220, 38, 38, 0.15);
  border: 1px solid rgba(248, 113, 113, 0.3);
}

.player-empty,
.player-empty-state {
  font-size: 0.74rem;
  opacity: 0.72;
}

@media (max-width: 1100px) {
  .player-grid {
    grid-template-columns: 1fr;
  }

  .player-banner {
    flex-direction: column;
  }

  .player-banner-metrics {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    min-width: 0;
  }

  .player-form,
  .player-list-item,
  .player-list-header {
    grid-template-columns: 1fr;
  }

  .player-actions {
    text-align: left;
  }
}
</style>
