mod credentials;
pub use credentials::*;

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

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

#[derive(Debug, Serialize, Clone)]
pub struct TenantScore {
    pub config: TenantConfig,
}

impl<T: Topology + TenantManager> Score<T> for TenantScore {
    fn create_interpret(&self) -> Box<dyn crate::interpret::Interpret<T>> {
        Box::new(TenantInterpret {
            tenant_config: self.config.clone(),
        })
    }

    fn name(&self) -> String {
        format!("{} TenantScore", self.config.name)
    }
}

#[derive(Debug)]
pub struct TenantInterpret {
    tenant_config: TenantConfig,
}

#[async_trait]
impl<T: Topology + TenantManager> Interpret<T> for TenantInterpret {
    async fn execute(
        &self,
        _inventory: &Inventory,
        topology: &T,
    ) -> Result<Outcome, InterpretError> {
        topology.provision_tenant(&self.tenant_config).await?;

        Ok(Outcome::success(format!(
            "Successfully provisioned tenant {} with id {}",
            self.tenant_config.name, self.tenant_config.id
        )))
    }

    fn get_name(&self) -> InterpretName {
        InterpretName::TenantInterpret
    }

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

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

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