use std::sync::Arc;

use folk_api::metrics::{CounterVec, GaugeVec, MetricsRegistry};

pub struct ProcessMetrics {
    up: Arc<dyn GaugeVec>,
    restarts_total: Arc<dyn CounterVec>,
    uptime_seconds: Arc<dyn GaugeVec>,
    exit_code: Arc<dyn GaugeVec>,
    status: Arc<dyn GaugeVec>,
}

impl ProcessMetrics {
    pub fn new(registry: &dyn MetricsRegistry) -> Self {
        Self {
            up: registry.gauge_vec(
                "folk_process_up",
                "Whether the process is running (1) or not (0)",
                &["name"],
            ),
            restarts_total: registry.counter_vec(
                "folk_process_restarts_total",
                "Total number of process restarts",
                &["name"],
            ),
            uptime_seconds: registry.gauge_vec(
                "folk_process_uptime_seconds",
                "Current instance uptime in seconds",
                &["name"],
            ),
            exit_code: registry.gauge_vec(
                "folk_process_exit_code",
                "Last exit code of the process",
                &["name"],
            ),
            status: registry.gauge_vec(
                "folk_process_status",
                "Process status (1 = active for that status label)",
                &["name", "status"],
            ),
        }
    }

    pub fn set_up(&self, name: &str, running: bool) {
        self.up
            .with_labels(&[name])
            .set(if running { 1 } else { 0 });
    }

    pub fn inc_restarts(&self, name: &str) {
        self.restarts_total.with_labels(&[name]).inc();
    }

    pub fn set_uptime(&self, name: &str, secs: f64) {
        self.uptime_seconds.with_labels(&[name]).set(secs as i64);
    }

    pub fn set_exit_code(&self, name: &str, code: i32) {
        self.exit_code.with_labels(&[name]).set(code as i64);
    }

    pub fn set_status(&self, name: &str, active_status: &str) {
        for s in &["running", "stopped", "failed"] {
            self.status
                .with_labels(&[name, s])
                .set(if *s == active_status { 1 } else { 0 });
        }
    }
}
