///|
pub(all) enum ProductLaunchAction {
  OpenOperatorWorkspace
  InspectProductStatus
  InspectReadinessReport
  RunCutoverChecklist
  OpenHandoffRunbook
  ArchiveLegacyApp
  ExportLaunchEvidence
} derive(Debug, Eq, ToJson, FromJson)

///|
pub(all) struct ProductLaunchBinding {
  id : String
  schema_id : String
  source_path : String
  redacted : Bool
} derive(Debug, Eq, ToJson, FromJson)

///|
pub(all) struct ProductLaunchPanel {
  id : String
  label : String
  ready : Bool
  binding_ids : Array[String]
} derive(Debug, Eq, ToJson, FromJson)

///|
pub(all) struct ProductLaunchManifest {
  id : String
  mount_path : String
  run_id : @domain.RunId
  ready : Bool
  blocking_gate_count : Int
  status_path : String
  bindings : Array[ProductLaunchBinding]
  panels : Array[ProductLaunchPanel]
  actions : Array[ProductLaunchAction]
  summary : String
} derive(Debug, Eq, ToJson, FromJson)

///|
pub fn product_launch_binding(
  id : String,
  schema_id : String,
  source_path : String,
  redacted? : Bool = false,
) -> ProductLaunchBinding {
  { id, schema_id, source_path, redacted }
}

///|
pub fn product_launch_panel(
  id : String,
  label : String,
  binding_ids : Array[String],
  ready? : Bool = true,
) -> ProductLaunchPanel {
  { id, label, ready, binding_ids }
}

///|
fn product_status_path(run_id : @domain.RunId) -> String {
  "records/product-status/\{run_id}.json"
}

///|
fn product_surface_path(run_id : @domain.RunId, name : String) -> String {
  "apps/moondesk-price-action/product-status/\{run_id}/\{name}.json"
}

///|
fn add_blocker(count : Int, passed : Bool) -> Int {
  if passed {
    count
  } else {
    count + 1
  }
}

///|
fn blocking_gate_count(status : MoonfishProductStatus) -> Int {
  add_blocker(
    add_blocker(
      add_blocker(
        add_blocker(
          add_blocker(
            add_blocker(0, status.acceptance_report.passed),
            status.readiness_report.ready,
          ),
          status.comparison_report.ready,
        ),
        status.cutover_plan.ready_to_cutover,
      ),
      status.handoff_report.ready,
    ),
    status.decommission_report.ready,
  )
}

///|
fn launch_bindings(
  status : MoonfishProductStatus,
) -> Array[ProductLaunchBinding] {
  let run_id = status.workspace.bundle.request.run_id
  [
    product_launch_binding(
      "product-status",
      "product-status",
      product_status_path(run_id),
    ),
    product_launch_binding(
      "workspace",
      "analysis-workspace",
      product_surface_path(run_id, "workspace"),
    ),
    product_launch_binding(
      "pack-manifest",
      "pack-manifest",
      product_surface_path(run_id, "pack-manifest"),
    ),
    product_launch_binding(
      "readiness", "cutover-readiness-report", "records/evaluations/cutover-readiness.json",
    ),
    product_launch_binding(
      "cutover-plan",
      "cutover-plan",
      "records/cutovers/\{run_id}.json",
    ),
    product_launch_binding(
      "operator-handoff",
      "operator-handoff-report",
      "records/handoffs/\{run_id}.json",
    ),
    product_launch_binding(
      "decommission",
      "decommission-report",
      "\{status.decommission_report.archive_root}/final-status.json",
    ),
  ]
}

///|
fn launch_panels(status : MoonfishProductStatus) -> Array[ProductLaunchPanel] {
  [
    product_launch_panel(
      "launch-overview",
      "Launch Overview",
      ["product-status", "readiness", "operator-handoff"],
      ready=blocking_gate_count(status) == 0,
    ),
    product_launch_panel(
      "cutover-checklist",
      "Cutover Checklist",
      ["readiness", "cutover-plan", "pack-manifest"],
      ready=status.readiness_report.ready &&
        status.cutover_plan.ready_to_cutover,
    ),
    product_launch_panel(
      "handoff-runbook",
      "Handoff Runbook",
      ["operator-handoff", "workspace"],
      ready=status.handoff_report.ready,
    ),
    product_launch_panel(
      "decommission-archive",
      "Decommission Archive",
      ["decommission", "cutover-plan"],
      ready=status.decommission_report.ready,
    ),
  ]
}

///|
fn launch_actions(ready : Bool) -> Array[ProductLaunchAction] {
  if ready {
    [
      OpenOperatorWorkspace,
      InspectProductStatus,
      InspectReadinessReport,
      RunCutoverChecklist,
      OpenHandoffRunbook,
      ArchiveLegacyApp,
      ExportLaunchEvidence,
    ]
  } else {
    [OpenOperatorWorkspace, InspectProductStatus, InspectReadinessReport]
  }
}

///|
fn launch_summary(manifest : ProductLaunchManifest) -> String {
  if manifest.ready {
    "product launch manifest ready with \{manifest.panels.length()} panel(s), \{manifest.actions.length()} action(s), and status at \{manifest.status_path}"
  } else {
    "product launch manifest blocked by \{manifest.blocking_gate_count} gate(s); inspect \{manifest.status_path}"
  }
}

///|
pub fn prepare_product_launch_manifest(
  status : MoonfishProductStatus,
) -> ProductLaunchManifest {
  let run_id = status.workspace.bundle.request.run_id
  let blocking_gate_count = blocking_gate_count(status)
  let ready = blocking_gate_count == 0
  let manifest : ProductLaunchManifest = {
    id: "moonfish-product-launch",
    mount_path: "apps/moondesk-price-action/product-status",
    run_id,
    ready,
    blocking_gate_count,
    status_path: product_status_path(run_id),
    bindings: launch_bindings(status),
    panels: launch_panels(status),
    actions: launch_actions(ready),
    summary: "",
  }
  { ..manifest, summary: launch_summary(manifest) }
}