use tici_service_discovery::election::leadership::EtcdLeadership;

use crate::{
    config::MetaServiceConfig, connection_pool::TiDBConnectionPool, meta::MetaStoreImplTiDB,
};

// The bootstrap is a helper used to ensure the meta store is initialized
// correctly. Only support bootstrapping with TiDB. If we later make the table
// to be system table, some methods may invalidate.
pub struct Bootstrap {
    tidb_pools: TiDBConnectionPool,
}

// Type alias for shortening the type name
type Store = MetaStoreImplTiDB<EtcdLeadership>;

impl Bootstrap {
    pub fn new(tidb_pools: TiDBConnectionPool) -> Self {
        Self { tidb_pools }
    }

    // Create a new Bootstrap instance with the given configuration.
    // This will create a new TiDB connection pool according to the config.
    // Should only be used in tests.
    pub fn new_with_config(config: &MetaServiceConfig) -> Self {
        let tidb_pools = TiDBConnectionPool::new(&config.tidb_server);
        Self { tidb_pools }
    }

    pub async fn is_bootstrapped(&self) -> Result<bool, anyhow::Error> {
        Store::is_bootstrapped(&self.tidb_pools).await
    }

    pub async fn ensure_bootstrapped(&self) -> Result<(), anyhow::Error> {
        let already_done = Store::is_bootstrapped(&self.tidb_pools).await?;
        if !already_done {
            Store::ensure_meta_schema(&self.tidb_pools).await?;
        }
        Ok(())
    }

    /// Dangerous method to clear all meta tables.
    pub async fn clear_all_meta(&self, then_create: bool) -> Result<(), anyhow::Error> {
        if then_create {
            Store::clear_all_meta(&self.tidb_pools).await?;
            Store::ensure_meta_schema(&self.tidb_pools).await
        } else {
            Store::clear_all_meta(&self.tidb_pools).await
        }
    }
}
