///|
/// Dose-response curve point with uncertainty.
pub struct AdvancedDosePoint {
  dose : Double
  count : Int
  mean_outcome : Double
  standard_error : Double
  lower : Double
  upper : Double
  weight_sum : Double
}

///|
/// Dose-response curve diagnostic.
pub struct DoseResponseAudit {
  points : Array[AdvancedDosePoint]
  monotonicity_score : Double
  maximum_gap : Double
  effective_sample_size : Double
  passes : Bool
}

///|
/// Builds weighted dose-response points over a grid.
pub fn advanced_dose_response(
  dose : Array[Double],
  outcome : Array[Double],
  weights : Array[Double],
  grid : Array[Double],
  bandwidth : Double,
) -> Array[AdvancedDosePoint] {
  let n = dose.length().min(outcome.length()).min(weights.length())
  let result : Array[AdvancedDosePoint] = Array::new(capacity=grid.length())
  for center in grid {
    let selected = Array::new()
    let selected_weights = Array::new()
    for i in 0.. Double {
  if points.length() < 2 {
    return 1.0
  }
  let mut concordant = 0
  let mut total = 0
  for i in 1..= points[i - 1].mean_outcome {
      concordant += 1
    }
  }
  concordant.to_double() / total.to_double()
}

///|
/// Computes the maximum adjacent uncertainty gap.
pub fn dose_maximum_gap(points : Array[AdvancedDosePoint]) -> Double {
  let mut result = 0.0
  for i in 1.. result {
      result = gap
    }
  }
  result
}

///|
/// Audits dose-response support and smoothness.
pub fn audit_dose_response(
  points : Array[AdvancedDosePoint],
  minimum_effective_sample_size? : Double = 5.0,
) -> DoseResponseAudit {
  let mut effective = 0.0
  for point in points {
    effective += point.weight_sum
  }
  let monotonicity = dose_monotonicity(points)
  let gap = dose_maximum_gap(points)
  {
    points,
    monotonicity_score: monotonicity,
    maximum_gap: gap,
    effective_sample_size: effective,
    passes: points.length() > 1 && effective >= minimum_effective_sample_size,
  }
}

///|
/// Integrates a dose-response curve by the trapezoidal rule.
pub fn integrate_dose_response(points : Array[AdvancedDosePoint]) -> Double {
  let mut result = 0.0
  for i in 1.. Double {
  if points.length() == 0 {
    return 0.0
  }
  let mut best = 0
  for i in 1.. points[best].mean_outcome {
      best = i
    }
  }
  points[best].dose
}

///|
/// Computes a finite-difference marginal effect along a dose grid.
pub fn dose_marginal_effect(
  points : Array[AdvancedDosePoint],
) -> Array[Array[Double]] {
  let result : Array[Array[Double]] = Array::new()
  for i in 1.. Array[Double] {
  [
    audit.points.length().to_double(),
    audit.monotonicity_score,
    audit.maximum_gap,
    audit.effective_sample_size,
    if audit.passes {
      1.0
    } else {
      0.0
    },
  ]
}