use std::path::PathBuf;

use async_trait::async_trait;
use log::info;
use serde::Serialize;

use crate::{
    config::HARMONY_CONFIG_DIR,
    data::{Id, Version},
    interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome},
    inventory::Inventory,
    score::Score,
    topology::Topology,
};

#[derive(Debug, Clone, Serialize)]
pub struct K3DInstallationScore {
    pub installation_path: PathBuf,
    pub cluster_name: String,
}

impl Default for K3DInstallationScore {
    fn default() -> Self {
        Self {
            installation_path: HARMONY_CONFIG_DIR.join("k3d"),
            cluster_name: "harmony".to_string(),
        }
    }
}

impl<T: Topology> Score<T> for K3DInstallationScore {
    fn create_interpret(&self) -> Box<dyn crate::interpret::Interpret<T>> {
        Box::new(K3dInstallationInterpret {
            score: self.clone(),
        })
    }

    fn name(&self) -> String {
        todo!()
    }
}

#[derive(Debug)]
pub struct K3dInstallationInterpret {
    score: K3DInstallationScore,
}

#[async_trait]
impl<T: Topology> Interpret<T> for K3dInstallationInterpret {
    async fn execute(
        &self,
        _inventory: &Inventory,
        _topology: &T,
    ) -> Result<Outcome, InterpretError> {
        let k3d = k3d_rs::K3d::new(
            self.score.installation_path.clone(),
            Some(self.score.cluster_name.clone()),
        );
        match k3d.ensure_installed().await {
            Ok(_client) => {
                let msg = format!("k3d cluster {} is installed ", self.score.cluster_name);
                info!("{msg}");
                Ok(Outcome::success(msg))
            }
            Err(msg) => Err(InterpretError::new(format!(
                "K3dInstallationInterpret failed to ensure k3d is installed : {msg}"
            ))),
        }
    }
    fn get_name(&self) -> InterpretName {
        InterpretName::K3dInstallation
    }
    fn get_version(&self) -> Version {
        todo!()
    }
    fn get_status(&self) -> InterpretStatus {
        todo!()
    }
    fn get_children(&self) -> Vec<Id> {
        todo!()
    }
}
