use std::sync::{Arc, Mutex};

use serde::Serialize;

use crate::{
    modules::monitoring::{
        kube_prometheus::types::ServiceMonitor,
        prometheus::{prometheus::Prometheus, prometheus_config::PrometheusConfig},
    },
    score::Score,
    topology::{
        HelmCommand, Topology,
        oberservability::monitoring::{AlertReceiver, AlertRule, AlertingInterpret},
        tenant::TenantManager,
    },
};

#[derive(Clone, Debug, Serialize)]
pub struct ApplicationPrometheusMonitoringScore {
    pub receivers: Vec<Box<dyn AlertReceiver<Prometheus>>>,
    pub rules: Vec<Box<dyn AlertRule<Prometheus>>>,
    pub service_monitors: Vec<ServiceMonitor>,
}

impl<T: Topology + HelmCommand + TenantManager> Score<T> for ApplicationPrometheusMonitoringScore {
    fn create_interpret(&self) -> Box<dyn crate::interpret::Interpret<T>> {
        let mut prom_config = PrometheusConfig::new();
        prom_config.alert_manager = true;

        let config = Arc::new(Mutex::new(prom_config));
        config
            .try_lock()
            .expect("couldn't lock config")
            .additional_service_monitors = self.service_monitors.clone();
        Box::new(AlertingInterpret {
            sender: Prometheus::new(),
            receivers: self.receivers.clone(),
            rules: self.rules.clone(),
        })
    }
    fn name(&self) -> String {
        "ApplicationPrometheusMonitoringScore".to_string()
    }
}
