///|
/// Calculate the Standard Deviation of NN intervals (SDNN).
pub fn calculate_sdnn(intervals : Array[Double]) -> Double {
  let n = intervals.length()
  if n <= 1 {
    return 0.0
  }
  let mut sum = 0.0
  for i in 0.. Double {
  let n = intervals.length()
  if n <= 1 {
    return 0.0
  }
  let mut sum_sq_diff = 0.0
  for i in 0..<(n - 1) {
    let diff = intervals[i + 1] - intervals[i]
    sum_sq_diff += diff * diff
  }
  let mean_sq_diff = sum_sq_diff / (n - 1).to_double()
  mean_sq_diff.sqrt()
}

///|
/// Calculate the percentage of successive RR intervals differing by more than threshold_ms.
pub fn calculate_pnn(
  intervals : Array[Double],
  threshold_ms : Double,
) -> Double {
  let n = intervals.length()
  if n <= 1 {
    return 0.0
  }
  let mut count = 0
  for i in 0..<(n - 1) {
    let diff = intervals[i + 1] - intervals[i]
    let abs_diff = if diff < 0.0 { -diff } else { diff }
    if abs_diff > threshold_ms {
      count += 1
    }
  }
  count.to_double() / (n - 1).to_double() * 100.0
}

///|
/// Calculate all time-domain HRV metrics for cleaned intervals.
pub fn calculate_metrics(
  intervals : Array[Double],
  config : HrvConfig,
  quality : QualityReport,
) -> HrvMetrics {
  let n = intervals.length()
  if n == 0 {
    return {
      mean_rr: 0.0,
      mean_hr: 0.0,
      sdnn: 0.0,
      rmssd: 0.0,
      pnn50: 0.0,
      pnn_custom: 0.0,
      quality,
    }
  }
  let mut sum = 0.0
  for i in 0.. 0.0 { 60000.0 / mean_rr } else { 0.0 }
  let sdnn = calculate_sdnn(intervals)
  let rmssd = calculate_rmssd(intervals)
  let pnn50 = calculate_pnn(intervals, 50.0)
  let pnn_custom = calculate_pnn(intervals, config.pnn_threshold)

  { mean_rr, mean_hr, sdnn, rmssd, pnn50, pnn_custom, quality }
}