///|
/// Stable schema name for machine-readable Moon Doctor reports.
pub let report_json_schema : String = "moon-doctor-report-v1"

///|
fn diagnostic_to_json(diagnostic : Diagnostic) -> Json {
  let location = match diagnostic.location {
    Some(value) =>
      Json::object({
        "path": Json::string(value.path),
        "line": Json::number(value.line.to_double()),
        "column": Json::number(value.column.to_double()),
      })
    None => Json::null()
  }
  Json::object({
    "severity": Json::string(diagnostic.severity.label()),
    "code": Json::string(diagnostic.code),
    "message": Json::string(diagnostic.message),
    "detail": Json::string(diagnostic.detail),
    "location": location,
    "remediation": Json::array(diagnostic.remediation.map(Json::string)),
  })
}

///|
fn release_checklist_to_json(checklist : Array[String]) -> Json {
  Json::array(checklist.map(Json::string))
}

///|
/// Render a deterministic JSON report for CI and other local tooling.
pub fn render_json_report(report : DoctorReport) -> String {
  let diagnostics = report.diagnostics.map(diagnostic_to_json)
  let document = Json::object({
    "format_version": Json::string(report_json_schema),
    "project": Json::string(report.root),
    "profile": Json::string(report.profile),
    "conclusion": Json::string(report.conclusion()),
    "score": Json::object({
      "grade": Json::string(report.score.grade),
      "status": Json::string(report.score.status),
      "errors": Json::number(report.score.errors.to_double()),
      "warnings": Json::number(report.score.warnings.to_double()),
      "infos": Json::number(report.score.infos.to_double()),
    }),
    "diagnostics": Json::array(diagnostics),
    "release_checklist": release_checklist_to_json(report.checklist),
  })
  document.stringify()
}