// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: 2026 clbbbb

///|
pub struct WorkspaceAudit {
  project : ProjectAudit
  readme : ReadmeAudit
  inventory : Array[LicenseUse]
  ignored_paths : Array[String]
} derive(Debug, Eq)

///|
pub fn workspace_audit(
  moon_mod : String,
  readme : String,
  paths : Array[String],
  sources : Array[String],
  policy : Policy,
) -> WorkspaceAudit {
  let filtered = filter_sources_by_rule(paths, sources)
  let scan_paths = filtered.0
  let scan_sources = filtered.1
  {
    project: project_audit(moon_mod, readme, scan_paths, scan_sources, policy),
    readme: audit_readme(readme),
    inventory: build_inventory(scan_paths, scan_sources),
    ignored_paths: ignored_paths(paths),
  }
}

///|
pub fn ignored_paths(paths : Array[String]) -> Array[String] {
  let rows : Array[String] = []
  for path in paths {
    if !should_scan_path(path) {
      rows.push(path)
    }
  }
  rows
}

///|
pub fn workspace_warnings(audit : WorkspaceAudit) -> Array[String] {
  unique_strings(audit.project.warnings + readme_audit_warnings(audit.readme))
}

///|
pub fn workspace_errors(
  audit : WorkspaceAudit,
  policy : Policy,
) -> Array[String] {
  unique_strings(
    audit.project.policy_errors +
    inventory_policy_errors(audit.inventory, policy),
  )
}

///|
pub fn workspace_score(audit : WorkspaceAudit, policy : Policy) -> Int {
  let mut score = audit_score(audit.project)
  score = score - readme_audit_warnings(audit.readme).length() * 3
  score = score - inventory_policy_errors(audit.inventory, policy).length() * 8
  if score < 0 {
    0
  } else {
    score
  }
}

///|
pub fn workspace_grade(audit : WorkspaceAudit, policy : Policy) -> String {
  let score = workspace_score(audit, policy)
  if score >= 90 {
    "A"
  } else if score >= 75 {
    "B"
  } else if score >= 60 {
    "C"
  } else {
    "D"
  }
}

///|
pub fn workspace_report(audit : WorkspaceAudit, policy : Policy) -> String {
  let rows : Array[String] = [
    "workspace grade: " + workspace_grade(audit, policy),
    "workspace score: " + workspace_score(audit, policy).to_string(),
    "",
    project_audit_report(audit.project),
    "",
    readme_audit_report_from_audit(audit.readme),
    "",
    inventory_report(audit.inventory),
  ]
  if !audit.ignored_paths.is_empty() {
    rows.push("")
    rows.push("ignored paths: " + join_with(audit.ignored_paths, ","))
  }
  join_lines(rows)
}

///|
pub fn readme_audit_report_from_audit(audit : ReadmeAudit) -> String {
  let rows : Array[String] = [
    "README title: " + bool_word(audit.has_title),
    "README license: " + bool_word(audit.has_license),
    "README install: " + bool_word(audit.has_install),
    "README usage: " + bool_word(audit.has_usage),
    "README example: " + bool_word(audit.has_example),
  ]
  push_section(rows, "README warnings", readme_audit_warnings(audit))
  join_lines(rows)
}

///|
pub fn audit_workspace_report(
  moon_mod : String,
  readme : String,
  paths : Array[String],
  sources : Array[String],
  policy : Policy,
) -> String {
  workspace_report(
    workspace_audit(moon_mod, readme, paths, sources, policy),
    policy,
  )
}