use std::sync::Arc;

use async_trait::async_trait;
use log::info;
use serde_json::Value;

use crate::{
    data::Version,
    inventory::Inventory,
    modules::{
        application::{Application, ApplicationFeature, OCICompliant},
        helm::chart::HelmChartScore,
    },
    score::Score,
    topology::{HelmCommand, Topology, Url},
};

/// ContinuousDelivery in Harmony provides this functionality :
///
/// - **Package** the application
/// - **Push** to an artifact registry
/// - **Deploy** to a testing environment
/// - **Deploy** to a production environment
///
/// It is intended to be used as an application feature passed down to an ApplicationInterpret. For
/// example :
///
/// ```rust,ignore
/// let app = RustApplicationScore {
///     name: "My Rust App".to_string(),
///     features: vec![ContinuousDelivery::default()],
/// };
/// ```
///
/// *Note :*
///
/// By default, the Harmony Opinionated Pipeline is built using these technologies :
///
/// - Gitea Action (executes pipeline steps)
/// - Docker to build an OCI container image
/// - Helm chart to package Kubernetes resources
/// - Harbor as artifact registru
/// - ArgoCD to install/upgrade/rollback/inspect k8s resources
/// - Kubernetes for runtime orchestration
#[derive(Debug, Default, Clone)]
pub struct ContinuousDelivery<A: OCICompliant> {
    pub application: Arc<A>,
}

#[async_trait]
impl<A: OCICompliant + Clone + 'static, T: Topology + HelmCommand + 'static> ApplicationFeature<T>
    for ContinuousDelivery<A>
{
    async fn ensure_installed(&self, topology: &T) -> Result<(), String> {
        let image = self.application.build_push_oci_image().await?;

        info!("Installing ContinuousDelivery feature");
        let cd_server = HelmChartScore {
            namespace: todo!(
                "ArgoCD Helm chart with proper understanding of Tenant, see how Will did it for Monitoring for now"
            ),
            release_name: todo!("argocd helm chart whatever"),
            chart_name: todo!(),
            chart_version: todo!(),
            values_overrides: todo!(),
            values_yaml: todo!(),
            create_namespace: todo!(),
            install_only: todo!(),
            repository: todo!(),
        };
        let interpret = cd_server.create_interpret();
        interpret.execute(&Inventory::empty(), topology);

        todo!("1. Create ArgoCD score that installs argo using helm chart, see if Taha's already done it
            2. Package app (docker image, helm chart)
            3. Push to registry if staging or prod
            4. Poke Argo
            5. Ensure app is up")
    }
    fn name(&self) -> String {
        "ContinuousDelivery".to_string()
    }
}

/// For now this is entirely bound to K8s / ArgoCD, will have to be revisited when we support
/// more CD systems
pub struct CDApplicationConfig {
    version: Version,
    helm_chart_url: Url,
    values_overrides: Value,
}

pub trait ContinuousDeliveryApplication {
    fn get_config(&self) -> CDApplicationConfig;
}
