///|
pub(all) enum HandoffGate {
  AcceptancePassed
  ReadinessPassed
  ComparisonReady
  AppToolMounted
  OperatorWorkflow
  CutoverChecklistReady
  RollbackReady
} derive(Debug, Eq, ToJson, FromJson)

///|
pub(all) enum HandoffStatus {
  HandoffPass
  HandoffBlocked
} derive(Debug, Eq, ToJson, FromJson)

///|
pub(all) struct HandoffFinding {
  gate : HandoffGate
  status : HandoffStatus
  path : String
  message : String
} derive(Debug, Eq, ToJson, FromJson)

///|
pub(all) struct HandoffRunbookStep {
  index : Int
  title : String
  action_path : String
  expected_evidence : String
} derive(Debug, Eq, ToJson, FromJson)

///|
pub(all) struct OperatorHandoffInput {
  acceptance_report : @acceptance.AcceptanceReport
  readiness_report : @evaluation.CutoverReadinessReport
  comparison_report : @comparison.CutoverComparisonReport
  cutover_plan : @cutover.CutoverPlan
  app_tool_manifest : @app.MoondeskAppToolManifest
} derive(Debug, Eq, ToJson, FromJson)

///|
pub(all) struct OperatorHandoffReport {
  ready : Bool
  launch_path : String
  pass_count : Int
  blocked_count : Int
  findings : Array[HandoffFinding]
  runbook : Array[HandoffRunbookStep]
  summary : String
} derive(Debug, Eq, ToJson, FromJson)

///|
pub fn operator_handoff_input(
  acceptance_report : @acceptance.AcceptanceReport,
  readiness_report : @evaluation.CutoverReadinessReport,
  comparison_report : @comparison.CutoverComparisonReport,
  cutover_plan : @cutover.CutoverPlan,
  app_tool_manifest : @app.MoondeskAppToolManifest,
) -> OperatorHandoffInput {
  {
    acceptance_report,
    readiness_report,
    comparison_report,
    cutover_plan,
    app_tool_manifest,
  }
}

///|
fn finding(
  gate : HandoffGate,
  status : HandoffStatus,
  path : String,
  message : String,
) -> HandoffFinding {
  { gate, status, path, message }
}

///|
fn runbook_step(
  index : Int,
  title : String,
  action_path : String,
  expected_evidence : String,
) -> HandoffRunbookStep {
  { index, title, action_path, expected_evidence }
}

///|
fn acceptance_finding(report : @acceptance.AcceptanceReport) -> HandoffFinding {
  if report.passed {
    finding(
      AcceptancePassed,
      HandoffPass,
      "acceptance-report",
      "product acceptance gates pass for canonical migration fixtures",
    )
  } else {
    finding(
      AcceptancePassed,
      HandoffBlocked,
      "acceptance-report",
      "acceptance report has unresolved product gates",
    )
  }
}

///|
fn readiness_finding(
  report : @evaluation.CutoverReadinessReport,
) -> HandoffFinding {
  if report.ready {
    finding(
      ReadinessPassed,
      HandoffPass,
      "cutover-readiness-report",
      "cutover readiness gates pass with comparison evidence",
    )
  } else {
    finding(
      ReadinessPassed,
      HandoffBlocked,
      "cutover-readiness-report",
      "cutover readiness has unresolved blockers",
    )
  }
}

///|
fn comparison_finding(
  report : @comparison.CutoverComparisonReport,
) -> HandoffFinding {
  if report.ready && report.pass_count == report.cases.length() {
    finding(
      ComparisonReady,
      HandoffPass,
      "cutover-comparison-report",
      "golden fixture, live snapshot, and rollback comparison checks pass",
    )
  } else {
    finding(
      ComparisonReady,
      HandoffBlocked,
      "cutover-comparison-report",
      "comparison report still needs review",
    )
  }
}

///|
fn app_mount_finding(manifest : @app.MoondeskAppToolManifest) -> HandoffFinding {
  if manifest.id == "moondesk-price-action" &&
    manifest.mount_path == "apps/moondesk-price-action" &&
    manifest.controls.length() >= 6 &&
    manifest.required_tools.contains("run_two_stage_routine") &&
    manifest.required_tools.contains("ingest_market_snapshot") {
    finding(
      AppToolMounted,
      HandoffPass,
      manifest.mount_path,
      "Moondesk price-action app-tool has mount path, controls, and required runtime tools",
    )
  } else {
    finding(
      AppToolMounted,
      HandoffBlocked,
      manifest.mount_path,
      "Moondesk app-tool manifest is missing launch requirements",
    )
  }
}

///|
fn operator_workflow_finding(
  manifest : @app.MoondeskAppToolManifest,
) -> HandoffFinding {
  let required_surfaces = [
    "run-analysis", "chart-panel", "event-stream-panel", "prompt-debug-panel", "start-follow-up",
    "export-run", "replay-run",
  ]
  let missing = required_surfaces.fold(init=0, fn(count, id) {
    if manifest.surfaces.any(fn(surface) { surface.id == id && surface.enabled }) {
      count
    } else {
      count + 1
    }
  })
  if missing == 0 && manifest.redacted_binding_count >= 3 {
    finding(
      OperatorWorkflow,
      HandoffPass,
      "moondesk-app-tool-manifest.surfaces",
      "operator workflow exposes run, chart, events, debug, follow-up, export, replay, and redacted bindings",
    )
  } else {
    finding(
      OperatorWorkflow,
      HandoffBlocked,
      "moondesk-app-tool-manifest.surfaces",
      "\{missing} required operator surface(s) are missing or disabled",
    )
  }
}

///|
fn checklist_finding(plan : @cutover.CutoverPlan) -> HandoffFinding {
  if plan.ready_to_cutover &&
    plan.checklist.length() >= 6 &&
    plan.imported_data_manifest_path != "" {
    finding(
      CutoverChecklistReady,
      HandoffPass,
      "cutover-plan.checklist",
      "cutover checklist has readiness, import, freeze, switch, rollback-window, and archive steps",
    )
  } else {
    finding(
      CutoverChecklistReady,
      HandoffBlocked,
      "cutover-plan.checklist",
      "cutover checklist is not executable yet",
    )
  }
}

///|
fn rollback_finding(plan : @cutover.CutoverPlan) -> HandoffFinding {
  if plan.rollback_days >= 1 &&
    plan.rollback_plan.length() >= 3 &&
    plan.rollback_plan.any(fn(step) { step.path == "../paa" }) {
    finding(
      RollbackReady,
      HandoffPass,
      "cutover-plan.rollback_plan",
      "PA Agent read-only rollback window and evidence capture steps are present",
    )
  } else {
    finding(
      RollbackReady,
      HandoffBlocked,
      "cutover-plan.rollback_plan",
      "rollback plan is incomplete",
    )
  }
}

///|
fn count_status(
  findings : Array[HandoffFinding],
  status : HandoffStatus,
) -> Int {
  findings.fold(init=0, fn(count, item) {
    if item.status == status {
      count + 1
    } else {
      count
    }
  })
}

///|
fn handoff_runbook(input : OperatorHandoffInput) -> Array[HandoffRunbookStep] {
  [
    runbook_step(
      0,
      "Open price-action app-tool",
      input.app_tool_manifest.mount_path,
      "moondesk-app-tool-manifest",
    ),
    runbook_step(
      1,
      "Run or ingest market evidence",
      "apps/moondesk-price-action/run-views/\{input.app_tool_manifest.run_id}",
      "analysis-workspace",
    ),
    runbook_step(
      2,
      "Review chart, events, prompts, and decision",
      "records/analyses/\{input.app_tool_manifest.run_id}.json",
      "analysis-record",
    ),
    runbook_step(
      3,
      "Export, replay, and attach follow-up",
      "records/exports/\{input.app_tool_manifest.run_id}.json",
      "export-manifest",
    ),
    runbook_step(
      4,
      "Execute cutover checklist",
      input.cutover_plan.imported_data_manifest_path,
      "cutover-plan",
    ),
  ]
}

///|
pub fn prepare_operator_handoff_report(
  input : OperatorHandoffInput,
) -> OperatorHandoffReport {
  let findings = [
    acceptance_finding(input.acceptance_report),
    readiness_finding(input.readiness_report),
    comparison_finding(input.comparison_report),
    app_mount_finding(input.app_tool_manifest),
    operator_workflow_finding(input.app_tool_manifest),
    checklist_finding(input.cutover_plan),
    rollback_finding(input.cutover_plan),
  ]
  let blocked_count = count_status(findings, HandoffBlocked)
  let pass_count = count_status(findings, HandoffPass)
  let ready = blocked_count == 0
  {
    ready,
    launch_path: input.app_tool_manifest.mount_path,
    pass_count,
    blocked_count,
    findings,
    runbook: handoff_runbook(input),
    summary: if ready {
      "operator handoff ready with \{pass_count}/\{findings.length()} gate(s) and \{handoff_runbook(input).length()} runbook step(s)"
    } else {
      "operator handoff blocked by \{blocked_count} gate(s)"
    },
  }
}