//! Metrics registration. Plugins create metric families and update counters,
//! gauges, and histograms.

use std::sync::Arc;

/// Single counter handle (one specific label combination).
pub trait Counter: Send + Sync + 'static {
    fn inc(&self);
    /// Increment the counter by `v`.
    ///
    /// Implementations must use **saturating** arithmetic: calling `inc_by`
    /// when the counter is at or near its maximum value must not wrap around
    /// to zero. Saturation at the maximum representable value is acceptable.
    fn inc_by(&self, v: u64);
    fn get(&self) -> u64;
}

/// Single gauge handle (one specific label combination).
pub trait Gauge: Send + Sync + 'static {
    fn set(&self, v: i64);
    fn inc(&self);
    fn dec(&self);
    fn get(&self) -> i64;
}

/// Single histogram handle (one specific label combination).
pub trait Histogram: Send + Sync + 'static {
    fn observe(&self, v: f64);
}

/// A counter metric family — use `with_labels` to get a concrete handle.
pub trait CounterVec: Send + Sync + 'static {
    fn with_labels(&self, labels: &[&str]) -> Arc<dyn Counter>;
}

pub trait GaugeVec: Send + Sync + 'static {
    fn with_labels(&self, labels: &[&str]) -> Arc<dyn Gauge>;
}

pub trait HistogramVec: Send + Sync + 'static {
    fn with_labels(&self, labels: &[&str]) -> Arc<dyn Histogram>;
}

/// Plugins register metric families here. Observers render them.
pub trait MetricsRegistry: Send + Sync + 'static {
    fn counter_vec(&self, name: &str, help: &str, label_keys: &[&str]) -> Arc<dyn CounterVec>;
    fn gauge_vec(&self, name: &str, help: &str, label_keys: &[&str]) -> Arc<dyn GaugeVec>;
    fn histogram_vec(&self, name: &str, help: &str, label_keys: &[&str]) -> Arc<dyn HistogramVec>;

    /// Render all registered metrics in Prometheus text exposition format.
    fn render(&self) -> String;
}
