///|
/// Summary statistics for reproducible monitoring reports.
pub(all) struct TransactionSummary {
  count : Int
  total_amount : Int
  minimum_amount : Int
  maximum_amount : Int
  customer_count : Int
  account_count : Int
}

///|
pub fn summarize(transactions : Array[Transaction]) -> TransactionSummary {
  if transactions.length() == 0 {
    return {
      count: 0,
      total_amount: 0,
      minimum_amount: 0,
      maximum_amount: 0,
      customer_count: 0,
      account_count: 0,
    }
  }
  let mut total = 0
  let mut minimum = transactions[0].amount
  let mut maximum = transactions[0].amount
  let customers : Array[String] = []
  let accounts : Array[String] = []
  for tx in transactions {
    total += tx.amount
    if tx.amount < minimum {
      minimum = tx.amount
    }
    if tx.amount > maximum {
      maximum = tx.amount
    }
    if !contains_string(customers, tx.customer_id) {
      customers.push(tx.customer_id)
    }
    if !contains_string(accounts, tx.account_id) {
      accounts.push(tx.account_id)
    }
  }
  {
    count: transactions.length(),
    total_amount: total,
    minimum_amount: minimum,
    maximum_amount: maximum,
    customer_count: customers.length(),
    account_count: accounts.length(),
  }
}

///|
pub fn amounts_above(
  transactions : Array[Transaction],
  threshold : Int,
) -> Array[Int] {
  let result : Array[Int] = []
  for tx in transactions {
    if tx.amount >= threshold {
      result.push(tx.amount)
    }
  }
  result
}

///|
pub fn count_by_region(
  transactions : Array[Transaction],
  region : String,
) -> Int {
  let mut count = 0
  for tx in transactions {
    if tx.region == region {
      count += 1
    }
  }
  count
}

///|
pub fn count_by_currency(
  transactions : Array[Transaction],
  currency : String,
) -> Int {
  let mut count = 0
  for tx in transactions {
    if tx.currency == currency {
      count += 1
    }
  }
  count
}

///|
pub fn total_for_customer(
  transactions : Array[Transaction],
  customer : String,
) -> Int {
  let mut total = 0
  for tx in transactions {
    if tx.customer_id == customer {
      total += tx.amount
    }
  }
  total
}

///|
pub fn total_for_account(
  transactions : Array[Transaction],
  account : String,
) -> Int {
  let mut total = 0
  for tx in transactions {
    if tx.account_id == account {
      total += tx.amount
    }
  }
  total
}

///|
pub fn percentile_rank(values : Array[Int], value : Int) -> Int {
  if values.length() == 0 {
    0
  } else {
    let mut below = 0
    for item in values {
      if item <= value {
        below += 1
      }
    }
    below * 100 / values.length()
  }
}

///|
pub fn moving_totals(
  transactions : Array[Transaction],
  window : Int,
) -> Array[Int] {
  let sorted = sort_by_time(transactions)
  let totals : Array[Int] = []
  for tx in sorted {
    totals.push(customer_volume_in_window(tx, sorted, window))
  }
  totals
}