#![deny(clippy::unwrap_used, clippy::expect_used)]
#![cfg_attr(test, allow(clippy::unwrap_used, clippy::expect_used))]
#![allow(dead_code)]
#![allow(missing_docs)]
#![allow(missing_debug_implementations)]
#![allow(unused_crate_dependencies)]
#![allow(clippy::float_arithmetic)]
#![allow(clippy::non_ascii_literal)]
#![allow(clippy::str_to_string)]
#![allow(clippy::partial_pub_fields)]
#![allow(clippy::multiple_inherent_impl)]
#![allow(clippy::same_name_method)]
#![allow(clippy::shadow_reuse)]
#![allow(clippy::shadow_unrelated)]
#![allow(clippy::shadow_same)]
#![allow(clippy::doc_markdown)]
#![allow(clippy::indexing_slicing)]
#![allow(clippy::missing_const_for_fn)]
#![allow(clippy::module_name_repetitions)]
#![allow(clippy::integer_division)]
#![allow(clippy::cognitive_complexity)]
#![allow(clippy::similar_names)]
#![allow(clippy::clone_on_ref_ptr)]
#![allow(clippy::too_many_lines)]
#![allow(clippy::as_conversions)]
#![allow(clippy::cast_precision_loss)]
#![allow(clippy::cast_possible_truncation)]
#![allow(clippy::default_numeric_fallback)]
#![allow(clippy::arithmetic_side_effects)]
#![allow(clippy::needless_range_loop)]
#![allow(clippy::into_iter_on_ref)]
#![allow(clippy::new_without_default)]
#![allow(clippy::manual_let_else)]
#![allow(clippy::unnecessary_wraps)]
#![allow(clippy::too_many_arguments)]
#![allow(clippy::must_use_candidate)]
#![allow(clippy::missing_errors_doc)]
#![allow(clippy::cast_sign_loss)]
#![allow(clippy::cast_possible_wrap)]
#![allow(clippy::cast_lossless)]
#![allow(clippy::unused_async)]
#![allow(clippy::match_same_arms)]
#![allow(clippy::unused_self)]
#![allow(clippy::map_err_ignore)]
#![allow(clippy::single_match_else)]
#![allow(clippy::wildcard_imports)]
#![allow(clippy::unnecessary_cast)]
#![allow(clippy::undocumented_unsafe_blocks)]
#![allow(clippy::redundant_clone)]
#![allow(clippy::redundant_closure)]
#![allow(clippy::type_complexity)]
#![allow(clippy::manual_clamp)]
#![allow(clippy::clone_on_copy)]
#![allow(clippy::should_implement_trait)]
#![allow(clippy::derivable_impls)]
#![allow(clippy::useless_conversion)]
#![allow(clippy::get_first)]
#![allow(clippy::len_zero)]
#![allow(clippy::assign_op_pattern)]
#![allow(clippy::if_same_then_else)]
#![allow(clippy::unused_enumerate_index)]
#![allow(clippy::doc_lazy_continuation)]
#![allow(clippy::doc_overindented_list_items)]
#![allow(clippy::single_char_add_str)]
#![allow(clippy::let_and_return)]
#![allow(clippy::useless_format)]
#![allow(clippy::manual_div_ceil)]
#![allow(clippy::io_other_error)]
#![allow(clippy::manual_range_contains)]
#![allow(clippy::unwrap_or_default)]
#![allow(clippy::used_underscore_binding)]
#![allow(clippy::trivially_copy_pass_by_ref)]
#![allow(clippy::needless_borrows_for_generic_args)]
#![allow(clippy::needless_borrow)]
#![allow(clippy::missing_safety_doc)]
#![allow(clippy::module_inception)]
#![allow(clippy::if_not_else)]

//! # Neural Risk Management System
//!
//! Advanced ML-driven risk management with neural VaR models, Kelly criterion optimization,
//! and real-time regime detection for production HFT systems using canonical types.

pub mod circuit_breakers;
pub mod graph_risk_model;
pub mod kelly_optimizer;
pub mod kelly_position_sizing_service;
pub mod position_sizing;
pub mod slippage;
pub mod var_models;

// Re-export key types from submodules
pub use circuit_breakers::MLCircuitBreaker;
pub use kelly_optimizer::{
    KellyCriterionOptimizer, KellyOptimizerConfig, KellyPositionRecommendation,
};
pub use position_sizing::PositionSizingNetwork;
pub use slippage::{FixedCostModel, LinearImpactConfig, LinearImpactModel, MarketImpactModel};
pub use var_models::{NeuralVarConfig, NeuralVarModel};

// Re-export core ML types used throughout risk modules
pub use ml_core::{MLError, MLResult, MarketDataSnapshot};

use std::collections::HashMap;

use chrono::{DateTime, Utc};
use ndarray::Array2;
use serde::{Deserialize, Serialize};

use common::{Price, Volume};

// AssetId type for risk management
#[derive(Debug, Clone, Serialize, Deserialize, Hash, PartialEq, Eq)]
pub struct AssetId(String);

/// Risk assessment levels
/// RiskLevel component.
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, PartialOrd)]
pub enum RiskLevel {
    VeryLow,
    Low,
    Medium,
    High,
    VeryHigh,
    Critical,
}

/// Portfolio risk profile
/// RiskProfile component.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RiskProfile {
    pub total_var_95: f64,       // 1-day 95% VaR
    pub total_var_99: f64,       // 1-day 99% VaR
    pub expected_shortfall: f64, // Expected tail loss
    pub maximum_drawdown: f64,   // Historical maximum drawdown
    pub current_drawdown: f64,   // Current drawdown from peak
    pub sharpe_ratio: f64,       // Risk-adjusted return
    pub sortino_ratio: f64,      // Downside risk-adjusted return
    pub calmar_ratio: f64,       // Return over maximum drawdown
    pub beta: f64,               // Market beta
    pub tracking_error: f64,     // Volatility vs benchmark
    pub concentration_risk: f64, // Single position concentration
    pub correlation_risk: f64,   // Average correlation risk
    pub liquidity_risk: f64,     // Liquidity-adjusted risk
    pub regime_risk: f64,        // Market regime risk factor
    pub overall_risk_score: f64, // Combined ML risk score (0-1)
    pub risk_level: RiskLevel,   // Categorical risk assessment
    pub timestamp: DateTime<Utc>,
}

/// Position-level risk metrics
/// PositionRisk component.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PositionRisk {
    pub asset_id: AssetId,
    pub position_size: f64,        // Current position size
    pub market_value: f64,         // Current market value
    pub var_contribution: f64,     // Contribution to portfolio VaR
    pub marginal_var: f64,         // Marginal VaR (change in portfolio VaR)
    pub component_var: f64,        // Component VaR (allocation of portfolio VaR)
    pub standalone_var: f64,       // Position VaR in isolation
    pub beta_to_portfolio: f64,    // Beta relative to portfolio
    pub correlation_risk: f64,     // Correlation with other positions
    pub liquidity_horizon: f64,    // Days to liquidate position
    pub concentration_weight: f64, // Weight in portfolio
    pub stress_loss: f64,          // Loss under stress scenarios
    pub kelly_optimal_size: f64,   // Kelly optimal position size
    pub recommended_size: f64,     // ML recommended position size
    pub risk_score: f64,           // Individual risk score (0-1)
    pub timestamp: DateTime<Utc>,
}

/// `Market` data for risk calculations
/// MarketData component.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MarketData {
    pub timestamp: DateTime<Utc>,
    pub prices: HashMap<AssetId, Price>,
    pub volumes: HashMap<AssetId, Volume>,
    pub volatilities: HashMap<AssetId, f64>,
    pub correlations: Array2<f64>,
    pub market_cap_weights: HashMap<AssetId, f64>,
    pub sector_exposures: HashMap<String, f64>,
}

/// Risk limits and constraints
/// RiskLimits component.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RiskLimits {
    pub max_portfolio_var: f64,   // Maximum portfolio VaR
    pub max_position_size: f64,   // Maximum single position size
    pub max_sector_exposure: f64, // Maximum sector exposure
    pub max_correlation: f64,     // Maximum position correlation
    pub max_drawdown: f64,        // Maximum allowed drawdown
    pub min_liquidity_days: f64,  // Minimum liquidity (days to exit)
    pub max_leverage: f64,        // Maximum portfolio leverage
    pub var_limit_buffer: f64,    // VaR limit buffer (e.g., 0.8 of limit)
}

impl Default for RiskLimits {
    fn default() -> Self {
        Self {
            max_portfolio_var: 0.02,   // 2% daily VaR limit
            max_position_size: 0.05,   // 5% maximum position size
            max_sector_exposure: 0.20, // 20% maximum sector exposure
            max_correlation: 0.70,     // 70% maximum correlation
            max_drawdown: 0.10,        // 10% maximum drawdown
            min_liquidity_days: 2.0,   // 2 days maximum liquidation time
            max_leverage: 3.0,         // 3x maximum leverage
            var_limit_buffer: 0.80,    // Use 80% of VaR limit
        }
    }
}

/// Comprehensive risk configuration
/// RiskConfig component.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RiskConfig {
    pub var_confidence_levels: Vec<f64>,
    pub lookback_days: usize,
    pub monte_carlo_simulations: usize,
    pub stress_scenarios: usize,
    pub regime_detection_window: usize,
    pub update_frequency_seconds: u32,
    pub enable_neural_var: bool,
    pub enable_regime_detection: bool,
    pub enable_ml_position_sizing: bool,
    pub enable_dynamic_hedging: bool,
    pub risk_limits: RiskLimits,
}

impl Default for RiskConfig {
    fn default() -> Self {
        Self {
            var_confidence_levels: vec![0.95, 0.99],
            lookback_days: 252,
            monte_carlo_simulations: 10_000,
            stress_scenarios: 1_000,
            regime_detection_window: 60,
            update_frequency_seconds: 60,
            enable_neural_var: true,
            enable_regime_detection: true,
            enable_ml_position_sizing: true,
            enable_dynamic_hedging: true,
            risk_limits: RiskLimits::default(),
        }
    }
}

/// Main neural risk management system
#[derive(Debug)]
pub struct NeuralRiskManager {
    config: RiskConfig,
    var_model: NeuralVarModel,
    kelly_optimizer: KellyCriterionOptimizer,
    position_sizer: PositionSizingNetwork,
    circuit_breaker: MLCircuitBreaker,
}

impl NeuralRiskManager {
    /// Create new neural risk management system
    pub fn new(config: RiskConfig) -> MLResult<Self> {
        let var_config = NeuralVarConfig {
            confidence_levels: config.var_confidence_levels.clone(),
            lookback_days: config.lookback_days,
            lookback_period: config.lookback_days,
            monte_carlo_simulations: config.monte_carlo_simulations,
            enable_stress_testing: true,
            hidden_layers: vec![128, 64, 32],
        };

        let var_model = NeuralVarModel::new(var_config)?;
        let kelly_optimizer = KellyCriterionOptimizer::new(Default::default())?;
        let position_sizer = PositionSizingNetwork::new(Default::default())?;
        let circuit_breaker = MLCircuitBreaker::new(Default::default())?;

        Ok(Self {
            config,
            var_model,
            kelly_optimizer,
            position_sizer,
            circuit_breaker,
        })
    }
}
