//! Cluster events for reactive state tracking.

use crate::types::Node;

/// Events emitted when cluster state changes.
///
/// Subscribe to these events using [`ServiceDiscovery::subscribe()`](crate::discovery::ServiceDiscovery::subscribe)
/// for event-driven architectures where you need to react to specific changes.
///
/// # Example
///
/// ```ignore
/// let mut events = discovery.subscribe();
/// while let Ok(event) = events.recv().await {
///     match event {
///         ClusterEvent::NodeJoined(n) => println!("Welcome {}", n.id),
///         ClusterEvent::NodeLeft(n) => println!("Goodbye {}", n.id),
///         ClusterEvent::LeaderElected(n) => println!("New leader: {}", n.id),
///         _ => {}
///     }
/// }
/// ```
#[derive(Debug, Clone, PartialEq)]
pub enum ClusterEvent {
    /// A new node joined the cluster.
    NodeJoined(Node),

    /// An existing node's metadata was updated (e.g., IP change, heartbeat).
    NodeUpdated {
        /// The node's previous state
        old: Node,
        /// The node's new state
        new: Node,
    },

    /// A node left the cluster (graceful shutdown or lease expiry).
    NodeLeft(Node),

    /// A new leader was elected.
    LeaderElected(Node),

    /// The leader stepped down or was lost. No current leader.
    LeaderLost,

    /// Initial synchronization with etcd completed.
    /// The cluster state is now accurate and watches are active.
    Ready,

    /// Lost connection to etcd. Attempting to reconnect.
    Disconnected,

    /// Reconnected to etcd after a disconnection.
    Reconnected,
}

impl std::fmt::Display for ClusterEvent {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            ClusterEvent::NodeJoined(n) => write!(f, "NodeJoined({})", n.id),
            ClusterEvent::NodeUpdated { old, new } => {
                write!(f, "NodeUpdated({}: {} -> {})", old.id, old.ip, new.ip)
            }
            ClusterEvent::NodeLeft(n) => write!(f, "NodeLeft({})", n.id),
            ClusterEvent::LeaderElected(n) => write!(f, "LeaderElected({})", n.id),
            ClusterEvent::LeaderLost => write!(f, "LeaderLost"),
            ClusterEvent::Ready => write!(f, "Ready"),
            ClusterEvent::Disconnected => write!(f, "Disconnected"),
            ClusterEvent::Reconnected => write!(f, "Reconnected"),
        }
    }
}
