//! Core types for TestCluster.

use crate::fault_injection::{ClockController, NetworkController};
use crate::harness::ChaosNode;
use std::sync::Arc;

/// A test cluster of ChaosNodes with shared fault injection controllers.
///
/// Provides methods for:
/// - Creating and managing multiple nodes
/// - Syncing data between nodes
/// - Verifying convergence
/// - Accessing fault controllers
///
/// # Example
///
/// ```ignore
/// let mut cluster = TestCluster::spawn(5).await?;
///
/// // Write some data
/// cluster.get_node_mut(0).write_assertion("key", "pred", 1000).await?;
///
/// // Create partition
/// cluster.network().partition(&[0, 1, 2], &[3, 4]);
///
/// // ... run tests ...
///
/// // Heal and verify
/// cluster.network().heal();
/// cluster.sync_all().await?;
/// cluster.assert_converged();
/// ```
pub struct TestCluster {
    /// The cluster nodes.
    pub(super) nodes: Vec<ChaosNode>,

    /// Shared network controller.
    pub(super) network: Arc<NetworkController>,

    /// Shared clock controller.
    pub(super) clock: Arc<ClockController>,

    /// Number of shards.
    pub(super) num_shards: u32,

    /// Replication factor.
    pub(super) replication_factor: u32,
}

impl std::fmt::Debug for TestCluster {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        use super::access::TestClusterAccessExt;
        use super::convergence::TestClusterConvergenceExt;

        f.debug_struct("TestCluster")
            .field("node_count", &self.nodes.len())
            .field("alive_count", &self.alive_node_indices().len())
            .field("converged", &self.is_converged())
            .finish()
    }
}
