//! Sharding error types.

use thiserror::Error;

use crate::ShardId;

/// Result type for sharding operations.
pub type ShardResult<T> = Result<T, ShardError>;

/// Errors that can occur during sharding operations.
#[derive(Error, Debug)]
pub enum ShardError {
    /// Invalid shard ID.
    #[error("Invalid shard ID: {0} (max: {1})")]
    InvalidShardId(ShardId, ShardId),

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

    /// Cross-shard message timeout.
    #[error("Cross-shard message timeout: {message_id}")]
    MessageTimeout { message_id: String },

    /// Cross-shard message failed.
    #[error("Cross-shard message failed: {0}")]
    MessageFailed(String),

    /// Invalid state root.
    #[error("Invalid state root for shard {0}")]
    InvalidStateRoot(ShardId),

    /// State proof verification failed.
    #[error("State proof verification failed: {0}")]
    ProofVerificationFailed(String),

    /// Leader election failed.
    #[error("Leader election failed for shard {0}: {1}")]
    LeaderElectionFailed(ShardId, String),

    /// Insufficient validators.
    #[error("Insufficient validators for shard {0}: have {1}, need {2}")]
    InsufficientValidators(ShardId, usize, usize),

    /// Resharding in progress.
    #[error("Resharding in progress, operation blocked")]
    ReshardingInProgress,

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

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

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

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

impl From<bincode::Error> for ShardError {
    fn from(err: bincode::Error) -> Self {
        ShardError::SerializationError(err.to_string())
    }
}

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