///|
pub(all) struct BatchItem {
  id : String
  text : String
} derive(Debug, Eq)

///|
pub(all) struct BatchResult {
  id : String
  result : DeidResult
} derive(Debug)

///|
pub(all) struct BatchSummary {
  document_count : Int
  finding_count : Int
  counts : Map[String, Int]
} derive(Debug)

///|
fn merge_counts(into : Map[String, Int], from : Map[String, Int]) -> Unit {
  for key, value in from {
    into[key] = into.get_or_default(key, 0) + value
  }
}

///|
pub fn redact_batch(
  items : Array[BatchItem],
  rules? : Array[Rule] = builtin_rules(),
  options? : DeidOptions = DeidOptions::default(),
) -> Array[BatchResult] raise DeidError {
  let results = []
  for item in items {
    results.push({ id: item.id, result: redact(item.text, rules~, options~) })
  }
  results
}

///|
pub fn summarize_batch(results : Array[BatchResult]) -> BatchSummary {
  let counts : Map[String, Int] = Map([])
  let mut total = 0
  for item in results {
    total += item.result.audit.finding_count
    merge_counts(counts, item.result.audit.counts)
  }
  { document_count: results.length(), finding_count: total, counts }
}