//! Error types for the risk management system
// #![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic)] // COMMENTED: Crate-level allows applied

use thiserror::Error;

use common::error::CommonError;
use common::types::Price;

use crate::risk_types::RiskSeverity;

/// Comprehensive error types for the risk management system
///
/// This enum covers all possible error conditions that can occur during risk
/// management operations, from configuration issues to critical safety violations.
/// Each error variant includes context-specific information to aid in debugging
/// and incident response.
#[derive(Debug, Error)]
#[error(transparent)]
pub enum RiskError {
    /// Configuration error occurred during system initialization or validation
    #[error("Configuration error: {0}")]
    Config(String),
    /// Database operation failed (connection, query, transaction, etc.)
    #[error("Database error: {0}")]
    Database(String),
    /// Position limit exceeded for a specific instrument
    #[error("Position limit exceeded: {instrument} has {current} but limit is {limit}")]
    PositionLimitExceeded {
        /// The financial instrument that exceeded its limit
        instrument: String,
        /// Current position size
        current: Price,
        /// Maximum allowed position size
        limit: Price,
    },
    /// Value at Risk limit exceeded, indicating portfolio risk is too high
    #[error("VaR limit exceeded: {var} exceeds limit of {limit}")]
    VarLimitExceeded {
        /// Current `VaR` value
        var: Price,
        /// Maximum allowed `VaR`
        limit: Price,
    },
    /// Drawdown limit exceeded, indicating excessive portfolio losses
    #[error("Drawdown limit exceeded: {drawdown}% exceeds limit of {limit}%")]
    DrawdownLimitExceeded {
        /// Current drawdown percentage
        drawdown: Price,
        /// Maximum allowed drawdown percentage
        limit: Price,
    },
    /// Daily loss limit exceeded, triggering risk controls
    #[error("Daily loss limit exceeded: {loss} exceeds limit of {limit}")]
    DailyLossLimitExceeded {
        /// Current daily loss amount
        loss: Price,
        /// Maximum allowed daily loss
        limit: Price,
    },
    /// Circuit breaker is active, preventing trading on an instrument
    #[error("Circuit breaker active for {instrument}: {reason}")]
    CircuitBreakerActive {
        /// The instrument with an active circuit breaker
        instrument: String,
        /// Reason why the circuit breaker was triggered
        reason: String,
    },
    /// Kill switch is active, immediately halting operations
    #[error("Kill switch active for {scope:?}: {message}")]
    KillSwitchActive {
        /// Scope of the kill switch (global, strategy, symbol)
        scope: crate::risk_types::KillSwitchScope,
        /// Detailed message about why the kill switch was activated
        message: String,
    },
    /// Market data is unavailable for required calculations
    #[error("Market data unavailable for {instrument}")]
    MarketDataUnavailable {
        /// The instrument for which market data is missing
        instrument: String,
    },
    /// Insufficient historical data for reliable risk calculations
    #[error("Insufficient historical data: need {required} but have {available}")]
    InsufficientHistoricalData {
        /// Number of data points required
        required: usize,
        /// Number of data points available
        available: usize,
    },
    /// Correlation calculation failed between instruments
    #[error("Correlation calculation failed: {reason}")]
    CorrelationCalculationFailed {
        /// Detailed reason for the correlation calculation failure
        reason: String,
    },
    /// Stress test scenario failed, indicating portfolio vulnerability
    #[error("Stress test failed: {scenario}")]
    StressTestFailed {
        /// The stress test scenario that failed
        scenario: String,
    },
    /// Performance metric violated its threshold
    #[error("Performance violation: {metric} = {value}, threshold = {threshold}")]
    PerformanceViolation {
        /// The performance metric that was violated
        metric: String,
        /// Current value of the metric
        value: Price,
        /// Threshold value that was exceeded
        threshold: Price,
    },
    /// Regulatory compliance rule was violated
    #[error("Compliance violation: {rule}")]
    ComplianceViolation {
        /// The compliance rule that was violated
        rule: String,
    },
    /// User authorization failed for the requested operation
    #[error("Authorization failed: {reason}")]
    AuthorizationFailed {
        /// Reason why authorization failed
        reason: String,
    },
    /// Order validation failed
    #[error("Invalid order: {reason}")]
    InvalidOrder {
        /// Reason why the order is invalid
        reason: String,
    },
    /// Required service is unavailable
    #[error("Service unavailable: {service}")]
    ServiceUnavailable {
        /// Name of the unavailable service
        service: String,
    },
    /// Operation timed out after specified duration
    #[error("Operation timeout: {timeout_ms}ms")]
    Timeout {
        /// Timeout duration in milliseconds
        timeout_ms: u64,
    },
    /// Data serialization/deserialization failed
    #[error("Serialization error: {0}")]
    Serialization(String),
    /// Network communication error occurred
    #[error("Network error: {0}")]
    Network(String),
    /// Internal system error - should not occur in normal operation
    #[error("Internal error: {0}")]
    Internal(String),
    /// Data validation failed for a specific field
    #[error("Validation error: {field} - {message}")]
    Validation {
        /// The field that failed validation
        field: String,
        /// Detailed validation error message
        message: String,
    },
    /// System resource was exhausted (memory, connections, etc.)
    #[error("Resource exhausted: {resource}")]
    ResourceExhausted {
        /// The resource that was exhausted
        resource: String,
    },
    /// Mathematical calculation failed
    #[error("Calculation error: {operation} failed - {reason}")]
    Calculation {
        /// The calculation operation that failed
        operation: String,
        /// Reason for the calculation failure
        reason: String,
    },
    /// Rate limit exceeded, operation must wait
    #[error("Rate limited: {remaining_ms}ms until reset")]
    RateLimited {
        /// Milliseconds remaining until rate limit resets
        remaining_ms: u64,
    },
    /// Order side (buy/sell) is invalid
    #[error("Invalid order side: {side}")]
    InvalidOrderSide {
        /// The invalid order side value
        side: String,
    },
    /// Order type is invalid or not supported
    #[error("Invalid order type: {order_type}")]
    InvalidOrderType {
        /// The invalid order type value
        order_type: String,
    },
    /// Order quantity is invalid (negative, zero, too large, etc.)
    #[error("Invalid quantity: {quantity}")]
    InvalidQuantity {
        /// The invalid quantity value
        quantity: String,
    },
    /// Order price is invalid (negative, zero, outside valid range, etc.)
    #[error("Invalid price: {price}")]
    InvalidPrice {
        /// The invalid price value
        price: String,
    },
    /// Generic connection error occurred
    #[error("Connection error: {message}")]
    ConnectionError {
        /// Detailed connection error message
        message: String,
    },
    /// Configuration-related error occurred
    #[error("Configuration error: {message}")]
    Configuration {
        /// Detailed configuration error message
        message: String,
    },
    /// Generic validation error occurred
    #[error("Validation error: {message}")]
    ValidationError {
        /// Detailed validation error message
        message: String,
    },
    /// Serialization/deserialization error occurred
    #[error("Serialization error: {message}")]
    SerializationError {
        /// Detailed serialization error message
        message: String,
    },

    // NEW: Enhanced error types for hardened risk management
    /// Type conversion failed between incompatible types
    #[error("Type conversion error: {from_type} to {to_type} failed - {reason}")]
    TypeConversion {
        /// Source type being converted from
        from_type: String,
        /// Target type being converted to
        to_type: String,
        /// Reason for the conversion failure
        reason: String,
    },

    /// Calculation error with simplified message
    #[error("Calculation error: {0}")]
    CalculationError(String),

    /// Required configuration parameter is missing
    #[error("Missing configuration: {config_key}")]
    MissingConfiguration {
        /// The configuration key that is missing
        config_key: String,
    },

    /// Environment validation failed - missing requirements
    #[error("Environment validation failed: {environment} requires {requirement}")]
    EnvironmentValidation {
        /// The environment being validated
        environment: String,
        /// The requirement that was not met
        requirement: String,
    },

    /// Data integrity check failed
    #[error("Data integrity error: {data_type} validation failed - {details}")]
    DataIntegrity {
        /// Type of data that failed integrity check
        data_type: String,
        /// Detailed information about the integrity failure
        details: String,
    },

    /// Resource is temporarily unavailable
    #[error("Resource unavailable: {resource} temporarily unavailable - {reason}")]
    ResourceUnavailable {
        /// The unavailable resource
        resource: String,
        /// Reason why the resource is unavailable
        reason: String,
    },

    /// Safety limit exceeded - immediate intervention required
    #[error("Safety limit exceeded: {limit_type} current={current} max={maximum}")]
    SafetyLimitExceeded {
        /// Type of safety limit that was exceeded
        limit_type: String,
        /// Current value that exceeded the limit
        current: String,
        /// Maximum allowed value
        maximum: String,
    },

    /// Emergency stop triggered - all operations must halt immediately
    #[error("Emergency stop triggered: {trigger} - immediate halt required")]
    EmergencyStop {
        /// The trigger that caused the emergency stop
        trigger: String,
    },

    /// Production safety violation detected
    #[error("Production safety violation: {violation} in {environment}")]
    ProductionSafety {
        /// Description of the safety violation
        violation: String,
        /// Environment where the violation occurred
        environment: String,
    },

    /// Broker system error occurred
    #[error("Broker connection error: {0}")]
    BrokerError(String),

    /// Broker connection failed
    #[error("Broker connection error: {message}")]
    BrokerConnection {
        /// Detailed broker connection error message
        message: String,
    },

    /// Connection to specific endpoint failed
    #[error("Connection failed to {endpoint}: {reason}")]
    Connection {
        /// The endpoint that failed to connect
        endpoint: String,
        /// Reason for the connection failure
        reason: String,
    },

    /// Market data system error occurred
    #[error("Market data error: {0}")]
    MarketDataError(String),

    /// Required data is unavailable for calculations
    #[error("Data unavailable: {resource} - {reason}")]
    DataUnavailable {
        /// The data resource that is unavailable
        resource: String,
        /// Reason why the data is unavailable
        reason: String,
    },

    /// Arithmetic overflow detected during calculation
    #[error("Arithmetic overflow: {operation} - {context}")]
    ArithmeticOverflow {
        /// The operation that overflowed
        operation: String,
        /// Context about the overflow
        context: String,
    },
}

/// Result type for risk management operations
pub type RiskResult<T> = Result<T, RiskError>;

/// Safe conversion helpers to eliminate `unwrap()` patterns
use num::ToPrimitive;
use rust_decimal::Decimal;
use std::fmt::Display;

/// Safely convert f64 to Price with context
pub fn f64_to_price_safe(value: f64, context: &str) -> RiskResult<Price> {
    Price::from_f64(value).map_err(|_| RiskError::TypeConversion {
        from_type: "f64".to_owned(),
        to_type: "Price".to_owned(),
        reason: format!("{context}: invalid f64 value {value}"),
    })
}

/// Safely convert f64 to Decimal with context
pub fn f64_to_decimal_safe(value: f64, context: &str) -> RiskResult<Decimal> {
    Decimal::try_from(value).map_err(|_| RiskError::TypeConversion {
        from_type: "f64".to_owned(),
        to_type: "Decimal".to_owned(),
        reason: format!("{context}: invalid f64 value {value}"),
    })
}

/// Safely convert Price to Decimal with context
pub fn price_to_decimal_safe(price: Price, context: &str) -> RiskResult<Decimal> {
    price.to_decimal().map_err(|_| RiskError::TypeConversion {
        from_type: "Price".to_owned(),
        to_type: "Decimal".to_owned(),
        reason: format!("{context}: price conversion failed"),
    })
}

/// Safely convert Decimal to f64 with context
pub fn decimal_to_f64_safe(decimal: Decimal, context: &str) -> RiskResult<f64> {
    decimal.to_f64().ok_or_else(|| RiskError::TypeConversion {
        from_type: "Decimal".to_owned(),
        to_type: "f64".to_owned(),
        reason: format!("{context}: decimal too large for f64"),
    })
}

/// Safely parse environment variable with context
pub fn parse_env_var<T: std::str::FromStr>(var_name: &str, context: &str) -> RiskResult<T>
where
    T::Err: Display,
{
    std::env::var(var_name)
        .map_err(|_| RiskError::MissingConfiguration {
            config_key: var_name.to_owned(),
        })?
        .parse()
        .map_err(|e| RiskError::EnvironmentValidation {
            environment: var_name.to_owned(),
            requirement: format!("{context}: {e}"),
        })
}

/// Safe division with zero check
pub fn safe_divide(numerator: Decimal, denominator: Decimal, context: &str) -> RiskResult<Decimal> {
    if denominator.is_zero() {
        return Err(RiskError::Calculation {
            operation: "division".to_owned(),
            reason: format!("{context}: division by zero"),
        });
    }
    Ok(numerator / denominator)
}

// ELIMINATED: Re-exports removed to force explicit imports

// Also support FoxhuntResult<T> for consistency with error-handling framework
// Removed core dependency - use core instead

impl RiskError {
    /// Get the severity level of this error
    #[must_use]
    pub const fn severity(&self) -> RiskSeverity {
        match self {
            RiskError::KillSwitchActive { .. }
            | RiskError::DailyLossLimitExceeded { .. }
            | RiskError::DrawdownLimitExceeded { .. }
            | RiskError::EmergencyStop { .. }
            | RiskError::ProductionSafety { .. } => RiskSeverity::Critical,

            RiskError::PositionLimitExceeded { .. }
            | RiskError::VarLimitExceeded { .. }
            | RiskError::CircuitBreakerActive { .. }
            | RiskError::ComplianceViolation { .. } => RiskSeverity::High,

            RiskError::PerformanceViolation { .. }
            | RiskError::MarketDataUnavailable { .. }
            | RiskError::AuthorizationFailed { .. } => RiskSeverity::Medium,

            _ => RiskSeverity::Low,
        }
    }

    /// Check if the error should trigger a kill switch
    #[must_use]
    pub const fn should_trigger_kill_switch(&self) -> bool {
        matches!(
            self,
            RiskError::DailyLossLimitExceeded { .. } | RiskError::DrawdownLimitExceeded { .. }
        )
    }

    /// Check if the error should trigger a circuit breaker
    #[must_use]
    pub const fn should_trigger_circuit_breaker(&self) -> bool {
        matches!(
            self,
            RiskError::PositionLimitExceeded { .. }
                | RiskError::VarLimitExceeded { .. }
                | RiskError::PerformanceViolation { .. }
        )
    }

    /// Get error code for logging and monitoring
    #[must_use]
    pub const fn error_code(&self) -> &'static str {
        match self {
            RiskError::Config(_) => "CONFIG_ERROR",
            RiskError::Database(_) => "DATABASE_ERROR",
            RiskError::PositionLimitExceeded { .. } => "POSITION_LIMIT_EXCEEDED",
            RiskError::VarLimitExceeded { .. } => "VAR_LIMIT_EXCEEDED",
            RiskError::DrawdownLimitExceeded { .. } => "DRAWDOWN_LIMIT_EXCEEDED",
            RiskError::DailyLossLimitExceeded { .. } => "DAILY_LOSS_LIMIT_EXCEEDED",
            RiskError::CircuitBreakerActive { .. } => "CIRCUIT_BREAKER_ACTIVE",
            RiskError::KillSwitchActive { .. } => "KILL_SWITCH_ACTIVE",
            RiskError::MarketDataUnavailable { .. } => "MARKET_DATA_UNAVAILABLE",
            RiskError::InsufficientHistoricalData { .. } => "INSUFFICIENT_HISTORICAL_DATA",
            RiskError::CorrelationCalculationFailed { .. } => "CORRELATION_CALCULATION_FAILED",
            RiskError::StressTestFailed { .. } => "STRESS_TEST_FAILED",
            RiskError::PerformanceViolation { .. } => "PERFORMANCE_VIOLATION",
            RiskError::ComplianceViolation { .. } => "COMPLIANCE_VIOLATION",
            RiskError::AuthorizationFailed { .. } => "AUTHORIZATION_FAILED",
            RiskError::InvalidOrder { .. } => "INVALID_ORDER",
            RiskError::ServiceUnavailable { .. } => "SERVICE_UNAVAILABLE",
            RiskError::Timeout { .. } => "TIMEOUT",
            RiskError::Serialization(_) => "SERIALIZATION_ERROR",
            RiskError::Network(_) => "NETWORK_ERROR",
            RiskError::Internal(_) => "INTERNAL_ERROR",
            RiskError::Validation { .. } => "VALIDATION_ERROR",
            RiskError::ResourceExhausted { .. } => "RESOURCE_EXHAUSTED",
            RiskError::Calculation { .. } => "CALCULATION_ERROR",
            RiskError::RateLimited { .. } => "RATE_LIMITED",
            RiskError::InvalidOrderSide { .. } => "INVALID_ORDER_SIDE",
            RiskError::InvalidOrderType { .. } => "INVALID_ORDER_TYPE",
            RiskError::InvalidQuantity { .. } => "INVALID_QUANTITY",
            RiskError::InvalidPrice { .. } => "INVALID_PRICE",
            RiskError::ConnectionError { .. } => "CONNECTION_ERROR",
            RiskError::Configuration { .. } => "CONFIGURATION_ERROR",
            RiskError::ValidationError { .. } => "VALIDATION_ERROR",
            RiskError::SerializationError { .. } => "SERIALIZATION_ERROR",

            // NEW: Enhanced error codes
            RiskError::TypeConversion { .. } => "TYPE_CONVERSION_ERROR",
            RiskError::CalculationError(_) => "CALCULATION_ERROR",
            RiskError::MissingConfiguration { .. } => "MISSING_CONFIGURATION",
            RiskError::EnvironmentValidation { .. } => "ENVIRONMENT_VALIDATION_ERROR",
            RiskError::DataIntegrity { .. } => "DATA_INTEGRITY_ERROR",
            RiskError::ResourceUnavailable { .. } => "RESOURCE_UNAVAILABLE",
            RiskError::SafetyLimitExceeded { .. } => "SAFETY_LIMIT_EXCEEDED",
            RiskError::EmergencyStop { .. } => "EMERGENCY_STOP",
            RiskError::ProductionSafety { .. } => "PRODUCTION_SAFETY_VIOLATION",
            RiskError::BrokerError(_) => "BROKER_ERROR",
            RiskError::BrokerConnection { .. } => "BROKER_CONNECTION_ERROR",
            RiskError::Connection { .. } => "CONNECTION_ERROR",
            RiskError::MarketDataError(_) => "MARKET_DATA_ERROR",
            RiskError::DataUnavailable { .. } => "DATA_UNAVAILABLE",
            RiskError::ArithmeticOverflow { .. } => "ARITHMETIC_OVERFLOW",
        }
    }
}

/// Convert from tokio timeout error
impl From<tokio::time::error::Elapsed> for RiskError {
    fn from(_: tokio::time::error::Elapsed) -> Self {
        RiskError::Timeout { timeout_ms: 0 }
    }
}

/// Convert from `anyhow::Error`
impl From<anyhow::Error> for RiskError {
    fn from(err: anyhow::Error) -> Self {
        RiskError::Internal(err.to_string())
    }
}

/// Convert from `CommonError` to `RiskError`  
impl From<CommonError> for RiskError {
    fn from(err: CommonError) -> Self {
        RiskError::Internal(format!("CommonError: {err}"))
    }
}

/// Convert from `CommonTypeError`
impl From<common::types::CommonTypeError> for RiskError {
    fn from(err: common::types::CommonTypeError) -> Self {
        RiskError::Internal(format!("CommonTypeError: {err}"))
    }
}

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

/// Convert from `std::num::ParseFloatError`
impl From<std::num::ParseFloatError> for RiskError {
    fn from(err: std::num::ParseFloatError) -> Self {
        RiskError::TypeConversion {
            from_type: "string".to_owned(),
            to_type: "f64".to_owned(),
            reason: err.to_string(),
        }
    }
}

/// Convert from `std::num::ParseIntError`
impl From<std::num::ParseIntError> for RiskError {
    fn from(err: std::num::ParseIntError) -> Self {
        RiskError::TypeConversion {
            from_type: "string".to_owned(),
            to_type: "integer".to_owned(),
            reason: err.to_string(),
        }
    }
}

/// Convert from `std::env::VarError`
impl From<std::env::VarError> for RiskError {
    fn from(err: std::env::VarError) -> Self {
        match err {
            std::env::VarError::NotPresent => RiskError::MissingConfiguration {
                config_key: "unknown".to_owned(),
            },
            std::env::VarError::NotUnicode(_) => RiskError::EnvironmentValidation {
                environment: "unknown".to_owned(),
                requirement: "valid unicode".to_owned(),
            },
        }
    }
}

/// Convert from `std::io::Error`
impl From<std::io::Error> for RiskError {
    fn from(err: std::io::Error) -> Self {
        RiskError::Network(format!("IO error: {err}"))
    }
}
