use std::sync::Arc;

use async_trait::async_trait;
use serde::Serialize;

use crate::{
    data::{Id, Version},
    interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome},
    inventory::Inventory,
    modules::{
        application::Application,
        monitoring::kube_prometheus::crd::crd_alertmanager_config::CRDPrometheus,
        prometheus::prometheus::PrometheusApplicationMonitoring,
    },
    score::Score,
    topology::{Topology, oberservability::monitoring::AlertReceiver},
};

#[derive(Debug, Clone, Serialize)]
pub struct ApplicationMonitoringScore {
    pub sender: CRDPrometheus,
    pub application: Arc<dyn Application>,
    pub receivers: Vec<Box<dyn AlertReceiver<CRDPrometheus>>>,
}

impl<T: Topology + PrometheusApplicationMonitoring<CRDPrometheus>> Score<T>
    for ApplicationMonitoringScore
{
    fn create_interpret(&self) -> Box<dyn Interpret<T>> {
        Box::new(ApplicationMonitoringInterpret {
            score: self.clone(),
        })
    }

    fn name(&self) -> String {
        "ApplicationMonitoringScore".to_string()
    }
}

#[derive(Debug)]
pub struct ApplicationMonitoringInterpret {
    score: ApplicationMonitoringScore,
}

#[async_trait]
impl<T: Topology + PrometheusApplicationMonitoring<CRDPrometheus>> Interpret<T>
    for ApplicationMonitoringInterpret
{
    async fn execute(
        &self,
        inventory: &Inventory,
        topology: &T,
    ) -> Result<Outcome, InterpretError> {
        topology
            .install_prometheus(
                &self.score.sender,
                inventory,
                Some(self.score.receivers.clone()),
            )
            .await
    }

    fn get_name(&self) -> InterpretName {
        todo!()
    }

    fn get_version(&self) -> Version {
        todo!()
    }

    fn get_status(&self) -> InterpretStatus {
        todo!()
    }

    fn get_children(&self) -> Vec<Id> {
        todo!()
    }
}
