//! Error types for privacy operations

use alloc::string::String;
use thiserror::Error;

/// Result type for privacy operations
pub type Result<T> = core::result::Result<T, Error>;

/// Errors that can occur during privacy operations
#[derive(Debug, Error)]
pub enum Error {
    /// Invalid blinding factor
    #[error("Invalid blinding factor: {0}")]
    InvalidBlindingFactor(String),

    /// Invalid commitment
    #[error("Invalid commitment: {0}")]
    InvalidCommitment(String),

    /// Range proof verification failed
    #[error("Range proof verification failed: {0}")]
    RangeProofFailed(String),

    /// Invalid range proof
    #[error("Invalid range proof: {0}")]
    InvalidRangeProof(String),

    /// Value out of range
    #[error("Value out of range: {value} (max: {max})")]
    ValueOutOfRange { value: u64, max: u64 },

    /// Invalid stealth address
    #[error("Invalid stealth address: {0}")]
    InvalidStealthAddress(String),

    /// Invalid view key
    #[error("Invalid view key: {0}")]
    InvalidViewKey(String),

    /// Invalid spend key
    #[error("Invalid spend key: {0}")]
    InvalidSpendKey(String),

    /// Ring signature verification failed
    #[error("Ring signature verification failed: {0}")]
    RingSignatureFailed(String),

    /// Invalid ring size
    #[error("Invalid ring size: {size} (min: {min}, max: {max})")]
    InvalidRingSize { size: usize, min: usize, max: usize },

    /// Key image already used (double spend)
    #[error("Key image already used: {0}")]
    KeyImageUsed(String),

    /// Invalid key image
    #[error("Invalid key image: {0}")]
    InvalidKeyImage(String),

    /// Transaction balance mismatch
    #[error("Transaction inputs and outputs don't balance")]
    BalanceMismatch,

    /// Missing proof
    #[error("Missing proof for output {0}")]
    MissingProof(usize),

    /// Invalid transaction
    #[error("Invalid transaction: {0}")]
    InvalidTransaction(String),

    /// Cryptographic error
    #[error("Cryptographic error: {0}")]
    CryptoError(String),

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

    /// Invalid point (not on curve)
    #[error("Invalid curve point: {0}")]
    InvalidPoint(String),

    /// Invalid scalar
    #[error("Invalid scalar: {0}")]
    InvalidScalar(String),
}

impl From<borsh::io::Error> for Error {
    fn from(e: borsh::io::Error) -> Self {
        Error::SerializationError(e.to_string())
    }
}
