///|
fn definition(
  id : String,
  category : RuleCategory,
  severity : Severity,
  title : String,
  description : String,
  remediation : String,
  profiles : Array[String],
) -> RuleDefinition {
  RuleDefinition::new(
    id, category, severity, title, description, remediation, profiles,
  )
}

///|
/// Return the complete stable v1 rule catalog.
pub fn rule_catalog() -> Array[RuleDefinition] {
  [
    definition(
      "missing_moon_mod",
      Manifest,
      Error,
      "moon.mod is required",
      "A MoonBit module needs moon.mod at its root.",
      "Create moon.mod with name, version, readme, repository and license metadata.",
      ["default", "github", "mooncakes", "release"],
    ),
    definition(
      "missing_root_moon_pkg",
      Package,
      Warn,
      "root moon.pkg is recommended",
      "A reusable root package should make its package boundary explicit.",
      "Add an empty or imported moon.pkg at the module root.",
      ["github", "mooncakes", "release"],
    ),
    definition(
      "missing_readme",
      Documentation,
      Warn,
      "README is recommended",
      "Public repositories need a visible project overview.",
      "Add README.md with usage, development and license sections.",
      ["default", "github", "mooncakes", "release"],
    ),
    definition(
      "missing_github_readme",
      Documentation,
      Info,
      "GitHub README is missing",
      "README.mbt.md is useful to MoonBit but GitHub normally shows README.md.",
      "Add README.md or a repository-supported link.",
      ["github", "release"],
    ),
    definition(
      "missing_license",
      Release,
      Error,
      "LICENSE is required",
      "Open-source reuse needs an explicit license file.",
      "Add the selected license text at repository root.",
      ["default", "github", "mooncakes", "release"],
    ),
    definition(
      "license_mismatch",
      Release,
      Warn,
      "License metadata should match",
      "moon.mod and LICENSE should describe the same license.",
      "Align moon.mod license with the LICENSE text.",
      ["github", "mooncakes", "release"],
    ),
    definition(
      "missing_gitignore",
      Release,
      Info,
      "Git ignore file is recommended",
      "Generated artifacts should stay out of commits.",
      "Add .gitignore with _build/ and .mooncakes/.",
      ["default", "github", "mooncakes", "release"],
    ),
    definition(
      "gitignore_missing_build",
      Release,
      Info,
      "Ignore build artifacts",
      "MoonBit build output should not be committed.",
      "Add _build/ to .gitignore.",
      ["github", "release"],
    ),
    definition(
      "gitignore_missing_mooncakes",
      Release,
      Info,
      "Ignore fetched dependencies",
      "Mooncakes downloads are normally local state.",
      "Add .mooncakes/ to .gitignore unless intentionally vendored.",
      ["github", "release"],
    ),
    definition(
      "missing_ci",
      Ci,
      Info,
      "CI is recommended",
      "Public packages benefit from repeatable quality gates.",
      "Add GitHub Actions to run moon check and moon test.",
      ["github", "release"],
    ),
    definition(
      "ci_missing_moon_check",
      Ci,
      Warn,
      "CI should run moon check",
      "A workflow without type checking cannot catch basic regressions.",
      "Add moon check to the workflow.",
      ["github", "release"],
    ),
    definition(
      "ci_missing_moon_test",
      Ci,
      Warn,
      "CI should run moon test",
      "A workflow should execute the package test suite.",
      "Add moon test to the workflow.",
      ["github", "release"],
    ),
    definition(
      "missing_examples",
      Documentation,
      Info,
      "Examples are recommended",
      "Runnable examples reduce adoption cost.",
      "Add an examples directory with source or documentation.",
      ["github", "mooncakes", "release"],
    ),
    definition(
      "examples_missing_content",
      Documentation,
      Info,
      "Examples need useful content",
      "An empty examples directory is not a user-facing example.",
      "Add a .mbt example, moon.pkg, or README under examples.",
      ["github", "mooncakes", "release"],
    ),
    definition(
      "missing_tests",
      Package,
      Warn,
      "Tests are recommended",
      "Core behavior should be protected by MoonBit tests.",
      "Add _test.mbt or _wbtest.mbt files.",
      ["default", "github", "mooncakes", "release"],
    ),
    definition(
      "missing_name",
      Manifest,
      Warn,
      "Module name is missing",
      "Packages need a stable module import name.",
      "Set name in moon.mod.",
      ["default", "mooncakes", "release"],
    ),
    definition(
      "missing_version",
      Manifest,
      Warn,
      "Version is missing",
      "Published packages need a semantic version.",
      "Set version in moon.mod.",
      ["mooncakes", "release"],
    ),
    definition(
      "missing_readme_metadata",
      Manifest,
      Warn,
      "Readme metadata is missing",
      "Package metadata should point to the readme file.",
      "Set readme in moon.mod.",
      ["mooncakes", "release"],
    ),
    definition(
      "missing_repository",
      Manifest,
      Info,
      "Repository metadata is missing",
      "A package should link to its source.",
      "Set repository in moon.mod.",
      ["github", "mooncakes", "release"],
    ),
    definition(
      "missing_description",
      Manifest,
      Info,
      "Description metadata is missing",
      "Search and discovery need a short description.",
      "Set description in moon.mod.",
      ["mooncakes", "release"],
    ),
    definition(
      "missing_keywords",
      Manifest,
      Info,
      "Keywords metadata is missing",
      "Keywords improve package discovery.",
      "Set keywords in moon.mod.",
      ["mooncakes", "release"],
    ),
    definition(
      "readme_target_missing",
      Manifest,
      Warn,
      "Readme target is missing",
      "moon.mod points to a file that does not exist.",
      "Update readme or add the referenced file.",
      ["github", "mooncakes", "release"],
    ),
    definition(
      "repository_placeholder",
      Manifest,
      Warn,
      "Repository is a placeholder",
      "A release should point to its real source repository.",
      "Replace the placeholder URL.",
      ["github", "mooncakes", "release"],
    ),
    definition(
      "repository_unusual",
      Manifest,
      Info,
      "Repository host is unusual",
      "Known hosts improve user confidence.",
      "Use a stable GitHub or Gitlink URL when possible.",
      ["github", "mooncakes", "release"],
    ),
    definition(
      "description_placeholder",
      Manifest,
      Info,
      "Description is a placeholder",
      "Placeholder metadata harms discovery.",
      "Write a concrete one-sentence summary.",
      ["mooncakes", "release"],
    ),
    definition(
      "keywords_placeholder",
      Manifest,
      Info,
      "Keywords are placeholders",
      "Placeholder keywords do not help search.",
      "Use domain-specific searchable terms.",
      ["mooncakes", "release"],
    ),
    definition(
      "package_missing_source",
      Package,
      Warn,
      "Package has no source",
      "A package manifest without source files is usually accidental.",
      "Add source files or remove the package manifest.",
      ["release"],
    ),
    definition(
      "package_missing_tests",
      Package,
      Info,
      "Package has no tests",
      "Multi-package modules should protect each package boundary.",
      "Add package-level tests or document why none are needed.",
      ["release"],
    ),
    definition(
      "package_missing_local_import",
      Package,
      Error,
      "Local import cannot be resolved",
      "A local package import does not map to any moon.pkg.",
      "Fix the import path or add the missing package.",
      ["default", "github", "mooncakes", "release"],
    ),
    definition(
      "package_cycle",
      Package,
      Error,
      "Local package dependency cycle",
      "MoonBit package imports must remain acyclic.",
      "Extract shared code into a lower-level package.",
      ["default", "github", "mooncakes", "release"],
    ),
  ]
}

///|
pub fn find_rule_definition(rule_id : String) -> RuleDefinition? {
  for rule in rule_catalog() {
    if rule.id == rule_id {
      return Some(rule)
    }
  }
  None
}

///|
pub fn rules_for_profile(profile : DoctorProfile) -> Array[RuleDefinition] {
  let expected = profile.label()
  let rules : Array[RuleDefinition] = []
  for rule in rule_catalog() {
    if rule.profiles.contains(expected) || rule.profiles.contains("default") {
      rules.push(rule)
    }
  }
  rules
}

///|
pub fn render_rule_catalog() -> String {
  let builder = StringBuilder()
  for rule in rule_catalog() {
    builder.write_string(
      "[" +
      rule.default_severity.label() +
      "] " +
      rule.id +
      " - " +
      rule.title +
      "\n",
    )
  }
  builder.to_string()
}