use crate::data::{Id, Version};
use crate::interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome};
use crate::inventory::Inventory;
use crate::score::Score;
use crate::topology::{HelmCommand, Topology};
use async_trait::async_trait;
use helm_wrapper_rs;
use helm_wrapper_rs::blocking::{DefaultHelmExecutor, HelmExecutor};
use non_blank_string_rs::NonBlankString;
use serde::Serialize;
use serde::de::DeserializeOwned;
use std::collections::HashMap;
use std::path::PathBuf;

#[derive(Debug, Clone, Serialize)]
pub struct HelmChartScore {
    pub namespace: Option<NonBlankString>,
    pub release_name: NonBlankString,
    pub chart_name: NonBlankString,
    pub chart_version: NonBlankString,
    pub values_overrides: Option<HashMap<NonBlankString, String>>,
}

impl<T: Topology> Score<T> for HelmChartScore {
    fn create_interpret(&self) -> Box<dyn Interpret<T>> {
        todo!()
    }

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

#[derive(Debug, Serialize)]
pub struct HelmChartInterpret {
    pub score: HelmChartScore,
}

#[async_trait]
impl<T: Topology + HelmCommand> Interpret<T> for HelmChartInterpret {
    async fn execute(
        &self,
        _inventory: &Inventory,
        _topology: &T,
    ) -> Result<Outcome, InterpretError> {
        let ns = self
            .score
            .namespace
            .as_ref()
            .unwrap_or(todo!("Get namespace from active kubernetes cluster"));
        let helm_executor = DefaultHelmExecutor::new();
        let res = helm_executor.install_or_upgrade(
            ns,
            &self.score.release_name,
            &self.score.chart_name,
            Some(&self.score.chart_version),
            self.score.values_overrides.as_ref(),
            None,
            None,
        );
        let status = match res {
            Ok(status) => status,
            Err(err) => return Err(InterpretError::new(err.to_string())),
        };

        match status {
            helm_wrapper_rs::HelmDeployStatus::Deployed => Ok(Outcome::new(
                InterpretStatus::SUCCESS,
                "Helm Chart deployed".to_string(),
            )),
            helm_wrapper_rs::HelmDeployStatus::PendingInstall => Ok(Outcome::new(
                InterpretStatus::RUNNING,
                "Helm Chart Pending install".to_string(),
            )),
            helm_wrapper_rs::HelmDeployStatus::PendingUpgrade => Ok(Outcome::new(
                InterpretStatus::RUNNING,
                "Helm Chart pending upgrade".to_string(),
            )),
            helm_wrapper_rs::HelmDeployStatus::Failed => Err(InterpretError::new(
                "Failed to install helm chart".to_string(),
            )),
        }
    }
    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!()
    }
}
