///|
pub(all) struct BenchmarkCase {
  name : String
  description : String
  documents : Array[String]
  expected_findings : Int
} derive(Debug, Eq)

///|
pub fn benchmark_cases() -> Array[BenchmarkCase] {
  [
    {
      name: "mixed-clinical",
      description: "Chinese-English identifiers in one outpatient note",
      documents: benchmark_fixture(),
      expected_findings: 15,
    },
    {
      name: "long-note",
      description: "Repeated synthetic discharge-note paragraphs",
      documents: [long_synthetic_note(4)],
      expected_findings: 20,
    },
    {
      name: "structured-fields",
      description: "Key-value fields used by ETL pipelines",
      documents: [
        "姓名=张三\n电话=13800138000\n邮箱=zhang@example.com\n住院号=MRN-778899\n地址=北京市海淀区中关村1号",
      ],
      expected_findings: 5,
    },
  ]
}

///|
pub fn long_synthetic_note(repetitions : Int) -> String {
  let paragraph = "患者:张三;身份证:110101199003071234;电话:13800138000;出生日期:1990-01-02;邮箱:zhang@example.com。\n"
  let builder = StringBuilder()
  let count = if repetitions < 0 { 0 } else { repetitions }
  for _ in 0.. BenchmarkCase? {
  for item in benchmark_cases() {
    if item.name == name {
      return Some(item)
    }
  }
  None
}

///|
pub fn benchmark_case_names() -> Array[String] {
  benchmark_cases().map(fn(item) { item.name })
}

///|
pub fn benchmark_case_summary(item : BenchmarkCase) -> String {
  [
    "name=\{item.name}",
    "description=\{item.description}",
    "documents=\{item.documents.length()}",
    "characters=\{item.documents.fold(init=0, (sum, text) => sum + text.char_length())}",
    "expected_findings=\{item.expected_findings}",
  ].join("\n")
}

///|
pub fn benchmark_catalog_summary() -> String {
  benchmark_cases().map(benchmark_case_summary).join("\n\n")
}

///|
pub fn run_benchmark_case(
  item : BenchmarkCase,
  repetitions : Int,
  config : RedactionConfig,
) -> BenchmarkResult raise DeidError {
  benchmark_once(item.name, item.documents, repetitions, config)
}

///|
pub fn run_all_benchmarks(
  repetitions : Int,
  config : RedactionConfig,
) -> Array[BenchmarkResult] raise DeidError {
  benchmark_cases().map(item => run_benchmark_case(item, repetitions, config))
}

///|
pub fn benchmark_results_text(results : Array[BenchmarkResult]) -> String {
  results.map(benchmark_summary).join("\n\n")
}

///|
pub fn benchmark_results_json(results : Array[BenchmarkResult]) -> String {
  "[" + results.map(benchmark_to_json).join(",") + "]"
}

///|
pub fn benchmark_findings_delta(
  item : BenchmarkCase,
  result : BenchmarkResult,
) -> Int {
  result.findings - item.expected_findings * result.repetitions
}

///|
pub fn benchmark_catalog_valid() -> Bool {
  benchmark_cases().all(fn(item) {
    !item.name.is_empty() && !item.documents.is_empty()
  })
}