//! Error types for Synor Economics

use thiserror::Error;

/// Result type for economics operations
pub type Result<T> = std::result::Result<T, EconomicsError>;

/// Economics error types
#[derive(Debug, Error)]
pub enum EconomicsError {
    /// Price feed unavailable
    #[error("Price feed unavailable: {0}")]
    PriceFeedUnavailable(String),

    /// Price too stale
    #[error("Price data stale: last update {0} ago")]
    PriceStale(String),

    /// Invalid price
    #[error("Invalid price: {0}")]
    InvalidPrice(String),

    /// Insufficient balance
    #[error("Insufficient balance: required {required}, available {available}")]
    InsufficientBalance {
        required: String,
        available: String,
    },

    /// Insufficient funds (with Decimal values)
    #[error("Insufficient funds: required {required}, available {available}")]
    InsufficientFunds {
        required: rust_decimal::Decimal,
        available: rust_decimal::Decimal,
    },

    /// Stale price with specific asset
    #[error("Price stale for {asset}: {age_seconds} seconds old")]
    StalePrice {
        asset: String,
        age_seconds: i64,
    },

    /// Account not found
    #[error("Account not found: {0}")]
    AccountNotFound(String),

    /// Invoice not found
    #[error("Invoice not found: {0}")]
    InvoiceNotFound(String),

    /// Invoice already paid
    #[error("Invoice {0} already paid")]
    InvoiceAlreadyPaid(String),

    /// Payment failed
    #[error("Payment failed: {0}")]
    PaymentFailed(String),

    /// Invalid metering event
    #[error("Invalid metering event: {0}")]
    InvalidMeteringEvent(String),

    /// Usage limit exceeded
    #[error("Usage limit exceeded: {resource} limit is {limit}, requested {requested}")]
    UsageLimitExceeded {
        resource: String,
        limit: String,
        requested: String,
    },

    /// Invalid fee distribution
    #[error("Invalid fee distribution: {0}")]
    InvalidFeeDistribution(String),

    /// Invalid pricing tier
    #[error("Invalid pricing tier: {0}")]
    InvalidPricingTier(String),

    /// Discount expired
    #[error("Discount {0} has expired")]
    DiscountExpired(String),

    /// Discount not applicable
    #[error("Discount not applicable: {0}")]
    DiscountNotApplicable(String),

    /// Service not configured
    #[error("Service not configured: {0}")]
    ServiceNotConfigured(String),

    /// Rate limit exceeded
    #[error("Rate limit exceeded: {0}")]
    RateLimitExceeded(String),

    /// Serialization error
    #[error("Serialization error: {0}")]
    Serialization(#[from] serde_json::Error),

    /// IO error
    #[error("IO error: {0}")]
    Io(#[from] std::io::Error),

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

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

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

impl EconomicsError {
    /// Check if the error is retryable
    pub fn is_retryable(&self) -> bool {
        matches!(
            self,
            EconomicsError::PriceFeedUnavailable(_)
                | EconomicsError::PaymentFailed(_)
                | EconomicsError::Database(_)
                | EconomicsError::Io(_)
                | EconomicsError::RateLimitExceeded(_)
        )
    }

    /// Get error code for API responses
    pub fn error_code(&self) -> &'static str {
        match self {
            EconomicsError::PriceFeedUnavailable(_) => "PRICE_FEED_UNAVAILABLE",
            EconomicsError::PriceStale(_) => "PRICE_STALE",
            EconomicsError::InvalidPrice(_) => "INVALID_PRICE",
            EconomicsError::InsufficientBalance { .. } => "INSUFFICIENT_BALANCE",
            EconomicsError::InsufficientFunds { .. } => "INSUFFICIENT_FUNDS",
            EconomicsError::StalePrice { .. } => "STALE_PRICE",
            EconomicsError::AccountNotFound(_) => "ACCOUNT_NOT_FOUND",
            EconomicsError::InvoiceNotFound(_) => "INVOICE_NOT_FOUND",
            EconomicsError::InvoiceAlreadyPaid(_) => "INVOICE_ALREADY_PAID",
            EconomicsError::PaymentFailed(_) => "PAYMENT_FAILED",
            EconomicsError::InvalidMeteringEvent(_) => "INVALID_METERING_EVENT",
            EconomicsError::UsageLimitExceeded { .. } => "USAGE_LIMIT_EXCEEDED",
            EconomicsError::InvalidFeeDistribution(_) => "INVALID_FEE_DISTRIBUTION",
            EconomicsError::InvalidPricingTier(_) => "INVALID_PRICING_TIER",
            EconomicsError::DiscountExpired(_) => "DISCOUNT_EXPIRED",
            EconomicsError::DiscountNotApplicable(_) => "DISCOUNT_NOT_APPLICABLE",
            EconomicsError::ServiceNotConfigured(_) => "SERVICE_NOT_CONFIGURED",
            EconomicsError::RateLimitExceeded(_) => "RATE_LIMIT_EXCEEDED",
            EconomicsError::Serialization(_) => "SERIALIZATION_ERROR",
            EconomicsError::Io(_) => "IO_ERROR",
            EconomicsError::Database(_) => "DATABASE_ERROR",
            EconomicsError::Configuration(_) => "CONFIGURATION_ERROR",
            EconomicsError::Internal(_) => "INTERNAL_ERROR",
        }
    }
}
