///|
pub(all) struct AnalysisExport {
  title : String
  profile : String
  summary : AnalysisSummary
  findings : Array[String]
  recommendations : Array[String]
  fingerprint : String
} derive(Debug, Eq, ToJson)

///|
pub fn make_analysis_export(
  title : String,
  profile : RuleProfileConfig,
  analysis : Analysis,
) -> AnalysisExport {
  let finding_lines : Array[String] = []
  for finding in analysis.findings {
    finding_lines.push(format_finding(finding))
  }
  let recommendation_lines : Array[String] = []
  for recommendation in recommendations(analysis) {
    recommendation_lines.push(recommendation_markdown(recommendation))
  }
  {
    title,
    profile: profile.label(),
    summary: summarize(analysis),
    findings: finding_lines,
    recommendations: recommendation_lines,
    fingerprint: analysis_fingerprint(analysis),
  }
}

///|
pub fn analysis_fingerprint(analysis : Analysis) -> String {
  let parts : Array[String] = []
  for finding in analysis.findings {
    parts.push(
      "\{rule_text(finding.rule)}:\{severity_text(finding.severity)}:\{finding.index}",
    )
  }
  parts.join("|")
}

///|
pub fn export_line_count(value : AnalysisExport) -> Int {
  5 + value.findings.length() + value.recommendations.length()
}

///|
pub fn export_csv(value : AnalysisExport) -> String {
  let lines : Array[String] = ["title,profile,total,errors,warnings,score"]
  lines.push(
    "\{value.title},\{value.profile},\{value.summary.total},\{value.summary.errors},\{value.summary.warnings},\{value.summary.score}",
  )
  for finding in value.findings {
    lines.push("finding,\{finding}")
  }
  lines.join("\n")
}

///|
pub fn export_markdown(value : AnalysisExport) -> String {
  let lines : Array[String] = [
    "# \{value.title}",
    "",
    "- Profile: \{value.profile}",
    "- Grade: \{value.summary.grade()}",
    "- Score: \{value.summary.score}",
    "",
    "## Findings",
    "",
  ]
  for finding in value.findings {
    lines.push("- \{finding}")
  }
  lines.push("")
  lines.push("## Recommendations")
  lines.push("")
  for recommendation in value.recommendations {
    lines.push(recommendation)
  }
  lines.join("\n")
}

///|
pub fn export_has_fingerprint(
  value : AnalysisExport,
  fingerprint : String,
) -> Bool {
  value.fingerprint == fingerprint
}

///|
pub fn export_grade(value : AnalysisExport) -> String {
  value.summary.grade()
}

///|
pub fn export_score(value : AnalysisExport) -> Int {
  value.summary.score
}

///|
pub fn export_findings_for(
  value : AnalysisExport,
  rule : RuleKind,
) -> Array[String] {
  let result : Array[String] = []
  let name = rule_text(rule)
  for finding in value.findings {
    if finding.contains(name) {
      result.push(finding)
    }
  }
  result
}

///|
pub fn export_is_clean(value : AnalysisExport) -> Bool {
  value.summary.errors == 0
}

///|
pub fn export_profile(value : AnalysisExport) -> String {
  value.profile
}

///|
pub fn export_summary_line(value : AnalysisExport) -> String {
  "\{export_grade(value)} / \{export_score(value)}"
}

///|
pub fn export_recommendation_count(value : AnalysisExport) -> Int {
  value.recommendations.length()
}

///|
pub fn export_findings_count(value : AnalysisExport) -> Int {
  value.findings.length()
}

///|
pub fn export_to_sections(value : AnalysisExport) -> Array[ReportSection] {
  [
    ReportSection::new(
      id="export-summary",
      title="Export summary",
      body=export_summary_line(value),
      priority=0,
    ),
    ReportSection::new(
      id="export-findings",
      title="Export findings",
      body=value.findings.join("\n"),
      priority=10,
    ),
    ReportSection::new(
      id="export-next-steps",
      title="Export next steps",
      body=value.recommendations.join("\n"),
      priority=20,
    ),
  ]
}