use ex3_common_error_info::ErrorInfo;
use ex3_node_types::CandidBlockHeight;

use ex3_canister_error::prelude::Error;
use ex3_canister_error::{impl_error_info_conversion, ErrorCode, ErrorKind};

/// The error type for asset vault
#[derive(Error, Debug, PartialEq, Clone, Eq)]
pub enum BlockchainError {
    #[error("Failed by parent hash not match")]
    FailedByParentHashDoesNotMatch,
    #[error("Failed by invalid height")]
    FailedByInvalidHeight,
    #[error("Failed by invalid version")]
    FailedByInvalidVersion,
    #[error("Non-existent block height")]
    NonExistentBlockHeight,
    #[error("Block height out of range, start is {start:?} , end is {end:?}")]
    BlockHeightOutOfRange {
        start: CandidBlockHeight,
        end: CandidBlockHeight,
    },
    #[error("Invalid consensus report")]
    InvalidConsensusReport,
}

impl ErrorCode for BlockchainError {
    fn error_code(&self) -> u32 {
        let root_code = ErrorKind::error_code(&ErrorKind::Blockchain);
        match self {
            BlockchainError::FailedByParentHashDoesNotMatch => root_code + 1,
            BlockchainError::FailedByInvalidHeight => root_code + 2,
            BlockchainError::FailedByInvalidVersion => root_code + 3,
            BlockchainError::NonExistentBlockHeight => root_code + 4,
            BlockchainError::BlockHeightOutOfRange { .. } => root_code + 5,
            BlockchainError::InvalidConsensusReport => root_code + 6,
        }
    }
}

impl_error_info_conversion!(BlockchainError);
