///|
pub(all) enum MissionReadinessCheckKind {
  TerrainReadiness
  CorridorReadiness
  IlluminationReadiness
  EnergyReadiness
  OperatorReviewReadiness
  RobotSimulationReadiness
} derive(Debug, Eq, ToJson, FromJson)

///|
pub(all) struct MissionReadinessCheck {
  check_id : String
  kind : MissionReadinessCheckKind
  label : String
  decision : TraverseDecision
  evidence_path : String
  reason : String
} derive(Debug, Eq, ToJson, FromJson)

///|
pub(all) struct MissionSimulationReadiness {
  readiness_id : String
  route_id : String
  decision : TraverseDecision
  robot_simulation_status : String
  checks : Array[MissionReadinessCheck]
  blocking_checks : Array[String]
  review_checks : Array[String]
  next_action : String
} derive(Debug, Eq, ToJson, FromJson)

///|
pub fn mission_readiness_check_kind_label(
  kind : MissionReadinessCheckKind,
) -> String {
  match kind {
    TerrainReadiness => "terrain"
    CorridorReadiness => "corridor"
    IlluminationReadiness => "illumination"
    EnergyReadiness => "energy"
    OperatorReviewReadiness => "operator-review"
    RobotSimulationReadiness => "robot-simulation"
  }
}

///|
pub fn mission_simulation_readiness_label(
  readiness : MissionSimulationReadiness,
) -> String {
  traverse_decision_label(readiness.decision)
}

///|
pub fn readiness_check(
  check_id : String,
  kind : MissionReadinessCheckKind,
  label : String,
  decision : TraverseDecision,
  evidence_path : String,
  reason : String,
) -> MissionReadinessCheck {
  { check_id, kind, label, decision, evidence_path, reason }
}

///|
fn combine_readiness_decision(
  left : TraverseDecision,
  right : TraverseDecision,
) -> TraverseDecision {
  if left == Block || right == Block {
    Block
  } else if left == Review || right == Review {
    Review
  } else {
    Allow
  }
}

///|
fn readiness_decision(
  checks : Array[MissionReadinessCheck],
) -> TraverseDecision {
  let mut decision = Allow
  for check in checks {
    decision = combine_readiness_decision(decision, check.decision)
  }
  decision
}

///|
fn check_ids_with_decision(
  checks : Array[MissionReadinessCheck],
  decision : TraverseDecision,
) -> Array[String] {
  let ids : Array[String] = []
  for check in checks {
    if check.decision == decision {
      ids.push(check.check_id)
    }
  }
  ids
}

///|
fn robot_simulation_status(decision : TraverseDecision) -> String {
  match decision {
    Allow => "simulation-ready"
    Review => "simulation-needs-review"
    Block => "simulation-blocked"
  }
}

///|
fn robot_simulation_check(decision : TraverseDecision) -> MissionReadinessCheck {
  readiness_check(
    "robot-simulation",
    RobotSimulationReadiness,
    "Robot simulation gate",
    decision,
    "artifact/simulation-preconditions.json",
    match decision {
      Allow => "Simulation may consume the selected-route packet"
      Review =>
        "Simulation needs operator review before the packet can be consumed"
      Block => "Simulation stays blocked until mission readiness checks clear"
    },
  )
}

///|
fn simulation_next_action(decision : TraverseDecision) -> String {
  match decision {
    Allow =>
      "selected route may advance to Simulation; hardware remains outside MoonMoon authority"
    Review =>
      "resolve review checks before Simulation consumes the selected-route packet"
    Block =>
      "keep Simulation blocked until terrain, corridor, illumination, energy, and operator review checks clear"
  }
}

///|
pub fn simulation_readiness(
  readiness_id : String,
  route_id : String,
  base_checks : Array[MissionReadinessCheck],
) -> MissionSimulationReadiness {
  let base_decision = readiness_decision(base_checks)
  let checks = base_checks
  checks.push(robot_simulation_check(base_decision))
  let decision = readiness_decision(checks)
  {
    readiness_id,
    route_id,
    decision,
    robot_simulation_status: robot_simulation_status(decision),
    checks,
    blocking_checks: check_ids_with_decision(checks, Block),
    review_checks: check_ids_with_decision(checks, Review),
    next_action: simulation_next_action(decision),
  }
}