use std::{collections::BTreeMap, fmt::Write};

use super::escape_label;

/// Low-cardinality labels recorded for a resilience decision.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct ResilienceMetricLabels {
    /// Transport such as `http`, `grpc` or `unknown`.
    pub transport: String,
    /// Component such as `breaker`, `shedder`, `concurrency` or `timeout`.
    pub component: String,
    /// Outcome such as `allowed`, `rejected`, `success` or `failure`.
    pub outcome: String,
}

impl ResilienceMetricLabels {
    /// Creates a resilience event label set.
    pub fn new(
        transport: impl Into<String>,
        component: impl Into<String>,
        outcome: impl Into<String>,
    ) -> Self {
        Self {
            transport: transport.into(),
            component: component.into(),
            outcome: outcome.into(),
        }
    }
}

pub(crate) fn render(output: &mut String, metrics: &BTreeMap<ResilienceMetricLabels, u64>) {
    output.push_str(
        "# HELP rs_zero_resilience_events_total Resilience events by transport, component and outcome.\n",
    );
    output.push_str("# TYPE rs_zero_resilience_events_total counter\n");
    for (labels, value) in metrics {
        writeln!(
            output,
            "rs_zero_resilience_events_total{{component=\"{}\",outcome=\"{}\",transport=\"{}\"}} {}",
            escape_label(&labels.component),
            escape_label(&labels.outcome),
            escape_label(&labels.transport),
            value
        )
        .ok();
    }
}
