///|
fn sarif_level(severity : Severity) -> String {
  match severity {
    Error => "error"
    Warning => "warning"
    Info => "note"
  }
}

///|
fn sarif_rule_name(code : StringView) -> String {
  match code {
    "MS001" => "module-name-required"
    "MS002" => "module-version-required"
    "MS003" => "license-declaration-required"
    "MS004" => "valid-spdx-expression"
    "MS005" => "repository-url-required"
    "MS006" => "license-file-required"
    "MS007" => "readme-required"
    "MS008" => "continuous-integration-recommended"
    "MS009" => "changelog-recommended"
    "MS010" => "gitignore-recommended"
    "MS011" => "license-declaration-matches-text"
    "MS012" => "license-text-recognized"
    "MS013" => "moonbit-source-required"
    "MS014" => "repository-url-valid"
    _ => "moonseal-finding"
  }
}

///|
fn sarif_rule_description(code : StringView) -> String {
  match code {
    "MS001" => "MoonBit modules must declare a package name."
    "MS002" => "Publishable MoonBit modules must declare a version."
    "MS003" => "Open-source modules must declare an SPDX license."
    "MS004" => "License declarations must use a supported SPDX expression."
    "MS005" => "Published modules should link to their source repository."
    "MS006" => "Open-source repositories must include a license file."
    "MS007" => "Repositories must include usage documentation."
    "MS008" => "Repositories should continuously build and test changes."
    "MS009" => "Published tools should document user-visible changes."
    "MS010" => "Repositories should exclude generated artifacts."
    "MS011" => "The manifest declaration must agree with the license text."
    "MS012" => "MoonSeal should be able to identify the license text."
    "MS013" => "A MoonBit project must contain MoonBit source code."
    "MS014" => "Repository metadata should use a valid Git transport URL."
    _ => "MoonSeal release-readiness finding."
  }
}

///|
fn sarif_help_uri(code : StringView) -> String {
  "https://github.com/liyun6666/moonseal#\{sarif_rule_name(code)}"
}

///|
fn sarif_unique_codes(findings : Array[Finding]) -> Array[String] {
  let codes = []
  for finding in findings {
    if !codes.any(fn(code) { code == finding.code }) {
      codes.push(finding.code)
    }
  }
  codes
}

///|
fn sarif_rule(code : String) -> Json {
  {
    "id": code,
    "name": sarif_rule_name(code),
    "shortDescription": { "text": sarif_rule_description(code) },
    "fullDescription": { "text": sarif_rule_description(code) },
    "helpUri": sarif_help_uri(code),
    "defaultConfiguration": {
      "level": if code == "MS010" {
        "note"
      } else {
        "warning"
      },
    },
    "properties": {
      "precision": "very-high",
      "tags": ["MoonBit", "supply-chain", "release-readiness"],
    },
  }
}

///|
fn sarif_location(path : String) -> Json {
  {
    "physicalLocation": {
      "artifactLocation": { "uri": path.replace_all(old="\\", new="/") },
      "region": { "startLine": 1, "startColumn": 1 },
    },
  }
}

///|
fn sarif_result(finding : Finding) -> Json {
  let locations : Array[Json] = if finding.path.is_empty() {
    []
  } else {
    [sarif_location(finding.path)]
  }
  {
    "ruleId": finding.code,
    "level": sarif_level(finding.severity),
    "message": { "text": finding.message },
    "locations": locations,
    "properties": {
      "moonsealSeverity": finding.severity.label(),
      "category": "release-readiness",
    },
  }
}

///|
/// Convert an audit report to SARIF 2.1.0 for GitHub Code Scanning and other
/// interoperable static-analysis consumers.
pub fn sarif(report : AuditReport) -> Json {
  let rules : Array[Json] = sarif_unique_codes(report.findings).map(sarif_rule)
  let results : Array[Json] = report.findings.map(sarif_result)
  {
    "$schema": "https://json.schemastore.org/sarif-2.1.0.json",
    "version": "2.1.0",
    "runs": [
      {
        "tool": {
          "driver": {
            "name": "MoonSeal",
            "informationUri": "https://github.com/liyun6666/moonseal",
            "semanticVersion": "0.2.1",
            "rules": rules,
          },
        },
        "automationDetails": {
          "id": "moonseal/\{report.project.name}",
          "description": { "text": "MoonSeal release-readiness audit" },
        },
        "invocations": [
          {
            "executionSuccessful": true,
            "properties": {
              "ready": report.is_ready(),
              "score": report.score,
              "moonbitSourceLines": report.moonbit_source_lines,
            },
          },
        ],
        "results": results,
        "properties": {
          "projectName": report.project.name,
          "projectVersion": report.project.version,
          "errorCount": report.error_count(),
          "warningCount": report.warning_count(),
        },
      },
    ],
  }
}

///|
pub fn render_sarif(report : AuditReport, indent? : Int = 2) -> String {
  sarif(report).stringify(indent~)
}