//! Error types for the cluster layer.

use thiserror::Error;

/// Errors that can occur during cluster operations.
#[derive(Debug, Error)]
pub enum ClusterError {
    /// Membership operation failed.
    #[error("Membership error: {0}")]
    Membership(String),

    /// Node not found in cluster.
    #[error("Node not found: {0}")]
    NodeNotFound(String),

    /// Sharding operation failed.
    #[error("Sharding error: {0}")]
    Sharding(String),

    /// Shard not found.
    #[error("Shard not found: {0}")]
    ShardNotFound(u32),

    /// No replicas available for shard.
    #[error("No replicas available for shard {0}")]
    NoReplicasAvailable(u32),

    /// Gateway routing failed.
    #[error("Gateway error: {0}")]
    Gateway(String),

    /// RPC communication failed.
    #[error("RPC error: {0}")]
    Rpc(#[from] stemedb_rpc::RpcError),

    /// Sync operation failed.
    #[error("Sync error: {0}")]
    Sync(#[from] stemedb_sync::SyncError),

    /// Storage operation failed.
    #[error("Storage error: {0}")]
    Storage(String),

    /// Configuration error.
    #[error("Configuration error: {0}")]
    Config(String),

    /// Network I/O error.
    #[error("Network error: {0}")]
    Network(String),

    /// Serialization/deserialization failed.
    #[error("Serialization error: {0}")]
    Serialization(String),

    /// Channel send/receive error.
    #[error("Channel error: {0}")]
    Channel(String),

    /// Timeout waiting for operation.
    #[error("Timeout: {0}")]
    Timeout(String),

    /// Internal consistency error.
    #[error("Internal error: {0}")]
    Internal(String),
}

impl From<stemedb_storage::error::StorageError> for ClusterError {
    fn from(err: stemedb_storage::error::StorageError) -> Self {
        ClusterError::Storage(err.to_string())
    }
}

impl From<std::io::Error> for ClusterError {
    fn from(err: std::io::Error) -> Self {
        ClusterError::Network(err.to_string())
    }
}

impl<T> From<tokio::sync::broadcast::error::SendError<T>> for ClusterError {
    fn from(err: tokio::sync::broadcast::error::SendError<T>) -> Self {
        ClusterError::Channel(format!("broadcast send failed: {err}"))
    }
}

impl From<tokio::sync::broadcast::error::RecvError> for ClusterError {
    fn from(err: tokio::sync::broadcast::error::RecvError) -> Self {
        ClusterError::Channel(format!("broadcast recv failed: {err}"))
    }
}

impl From<serde_json::Error> for ClusterError {
    fn from(err: serde_json::Error) -> Self {
        ClusterError::Serialization(err.to_string())
    }
}

/// Result type for cluster operations.
pub type Result<T> = std::result::Result<T, ClusterError>;
