///|
/// All deterministic report representations produced from one analysis result.
pub(all) struct ReportBundle {
  report : DoctorReport
  remediation : RemediationPlan
  scorecard : QualityScorecard
  text : String
  json : String
  sarif : String
  markdown : String
} derive(Debug, Eq)

///|
pub fn ReportBundle::new(report : DoctorReport) -> ReportBundle {
  let remediation = build_remediation_plan(report)
  let scorecard = build_quality_scorecard(report)
  {
    report,
    remediation,
    scorecard,
    text: render_report(report),
    json: render_json_report(report),
    sarif: render_sarif_report(report),
    markdown: render_markdown_report(report),
  }
}

///|
pub fn ReportBundle::for_format(
  self : ReportBundle,
  format : String,
) -> String? {
  match format {
    "text" => Some(self.text)
    "json" => Some(self.json)
    "sarif" => Some(self.sarif)
    "markdown" | "md" => Some(self.markdown)
    _ => None
  }
}

///|
pub fn ReportBundle::summary_json(self : ReportBundle) -> String {
  Json::object({
    "report": Json::string(self.json),
    "sarif": Json::string(self.sarif),
    "markdown": Json::string(self.markdown),
    "scorecard": quality_scorecard_to_json(self.scorecard),
    "remediation": remediation_plan_to_json(self.remediation),
  }).stringify()
}

///|
pub fn ReportBundle::release_ready(self : ReportBundle) -> Bool {
  self.report.score.errors == 0 && self.report.score.warnings == 0
}

///|
pub fn ReportBundle::artifact_names() -> Array[String] {
  [
    "moon-doctor-report.txt", "moon-doctor-report.json", "moon-doctor-report.sarif",
    "moon-doctor-report.md",
  ]
}

///|
pub fn render_bundle_index(bundle : ReportBundle) -> String {
  let builder = StringBuilder()
  builder.write_string("Moon Doctor artifact index\n")
  builder.write_string("Project: " + bundle.report.root + "\n")
  builder.write_string("Profile: " + bundle.report.profile + "\n")
  builder.write_string("Conclusion: " + bundle.report.conclusion() + "\n")
  builder.write_string(
    "Quality grade: " +
    bundle.scorecard.grade +
    " (\{bundle.scorecard.percentage}%)\n",
  )
  builder.write_string("Artifacts:\n")
  for name in ReportBundle::artifact_names() {
    builder.write_string("- " + name + "\n")
  }
  builder.to_string()
}

///|
pub fn render_bundle_markdown(bundle : ReportBundle) -> String {
  let builder = StringBuilder()
  builder.write_string("# Moon Doctor artifact bundle\n\n")
  builder.write_string("- Project: `" + bundle.report.root + "`\n")
  builder.write_string("- Profile: `" + bundle.report.profile + "`\n")
  builder.write_string("- Conclusion: **" + bundle.report.conclusion() + "**\n")
  builder.write_string(
    "- Quality: **" +
    bundle.scorecard.grade +
    " (\{bundle.scorecard.percentage}%)**\n\n",
  )
  builder.write_string(bundle.markdown)
  builder.to_string()
}