use std::sync::Arc;

use async_trait::async_trait;
use kube::{CustomResource, api::ObjectMeta};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

use crate::{
    interpret::{InterpretError, Outcome},
    inventory::Inventory,
    topology::{
        HelmCommand, K8sclient, Topology,
        installable::Installable,
        k8s::K8sClient,
        oberservability::monitoring::{AlertReceiver, AlertSender},
        tenant::TenantManager,
    },
};

#[derive(CustomResource, Serialize, Deserialize, Debug, Clone, JsonSchema)]
#[kube(
    group = "monitoring.coreos.com",
    version = "v1alpha1",
    kind = "AlertmanagerConfig",
    plural = "alertmanagerconfigs",
    namespaced
)]
pub struct AlertmanagerConfigSpec {
    #[serde(flatten)]
    pub data: serde_json::Value,
}

#[derive(Debug, Clone)]
pub struct CRDAlertManager {
    pub alertmanager_configs: AlertmanagerConfig,
    pub namespace: String,
    pub client: Arc<K8sClient>,
}

impl AlertSender for CRDAlertManager {
    fn name(&self) -> String {
        "CRDAlertManager".to_string()
    }
}

impl Clone for Box<dyn AlertReceiver<CRDAlertManager>> {
    fn clone(&self) -> Self {
        self.clone_box()
    }
}

impl Serialize for Box<dyn AlertReceiver<CRDAlertManager>> {
    fn serialize<S>(&self, _serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        todo!()
    }
}

#[async_trait]
pub trait CRDAlertManagerReceiver:
    AlertReceiver<CRDAlertManager> + Send + Sync + std::fmt::Debug
{
    fn name(&self) -> String;
    async fn configure_receiver(&self, client: &Arc<K8sClient>, ns: String) -> AlertmanagerConfig;
    // This new method is for cloning the trait object
    fn clone_box(&self) -> Box<dyn CRDAlertManagerReceiver>;
}

impl Clone for Box<dyn CRDAlertManagerReceiver> {
    fn clone(&self) -> Self {
        CRDAlertManagerReceiver::clone_box(self.as_ref())
    }
}

impl Serialize for Box<dyn CRDAlertManagerReceiver> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        todo!()
    }
}
