///|
fn metric_label(service : String, window : String) -> String {
  "service=\"\{escape_json(service)}\",window=\"\{escape_json(window)}\""
}

///|
pub fn BudgetReport::to_metrics(
  self : BudgetReport,
  service : String,
) -> String {
  let labels = metric_label(service, self.window.name)
  let result = StringBuilder()
  result.write_string(
    "# HELP moonslokit_slo_availability_bp Current availability in basis points\\n",
  )
  result.write_string("# TYPE moonslokit_slo_availability_bp gauge\\n")
  result.write_string("moonslokit_slo_availability_bp{")
  result.write_string(labels)
  result.write_string("} \{self.window.availability_bp()}\\n")
  result.write_string("moonslokit_slo_error_budget_consumed_bp{")
  result.write_string(labels)
  result.write_string("} \{self.consumed_bp}\\n")
  result.write_string("moonslokit_slo_remaining_bad{")
  result.write_string(labels)
  result.write_string("} \{self.remaining_bad}\\n")
  result.to_string()
}

///|
pub fn BurnReport::to_metrics(self : BurnReport, service : String) -> String {
  let labels = metric_label(service, self.window.name)
  "moonslokit_slo_burn_rate_x100{\{labels}} \{self.burn_rate_x100}\\n"
}

///|
pub fn ServiceEvaluation::to_metrics(self : ServiceEvaluation) -> String {
  let result = StringBuilder()
  result.write_string(self.budget.to_metrics(self.service))
  for report in self.multi_window.reports {
    result.write_string(report.to_metrics(self.service))
  }
  result.write_string(
    "moonslokit_slo_healthy{service=\"\{escape_json(self.service)}\"} ",
  )
  result.write_string(if self.healthy() { "1\\n" } else { "0\\n" })
  result.to_string()
}

///|
pub fn PortfolioSummary::to_metrics(self : PortfolioSummary) -> String {
  let labels = "portfolio=\"\{escape_json(self.portfolio)}\""
  "moonslokit_portfolio_services{\{labels}} \{self.service_count}\\nmoonslokit_portfolio_healthy{\{labels}} \{self.healthy_count}\\nmoonslokit_portfolio_availability_bp{\{labels}} \{self.availability_bp}\\n"
}

///|
pub fn SloTarget::to_metrics(self : SloTarget) -> String {
  "moonslokit_slo_target_bp{target=\"\{escape_json(self.name)}\"} \{self.target_bp}\\n"
}

///|
pub fn metrics_document(
  target : SloTarget,
  budgets : Array[BudgetReport],
  service : String,
) -> String {
  let result = StringBuilder()
  result.write_string(target.to_metrics())
  for budget in budgets {
    result.write_string(budget.to_metrics(service))
  }
  result.to_string()
}