//! HFT Latency Benchmark for Backtesting Module
//!
//! Validates sub-50μs latency targets for critical trading paths

use backtesting::{
    strategy_runner::{AdaptiveStrategyConfig, AdaptiveStrategyRunner},
    Strategy, StrategyContext,
};
use chrono::Utc;
use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion};
use rust_decimal::Decimal;
use std::collections::HashMap;
use std::time::{Duration, Instant};

// Import common types
use common::{Price, Quantity, Symbol};
use trading_engine::types::events::MarketEvent;

/// Benchmark market event to trading signal latency
fn bench_market_event_latency(c: &mut Criterion) {
    let rt = tokio::runtime::Runtime::new().unwrap();

    c.bench_function("market_event_to_signal_latency", |b| {
        b.iter(|| {
            rt.block_on(async {
                // Create optimized strategy runner
                let config = AdaptiveStrategyConfig {
                    active_models: vec!["TLOB".to_string()], // Single model for latency test
                    min_confidence: 0.6,
                    max_position_size: 0.01,
                    lookback_period: 20, // Minimal lookback for speed
                    ..Default::default()
                };

                let mut strategy = AdaptiveStrategyRunner::new(config);

                // Initialize with minimal capital
                let initial_capital = Decimal::from(10000);
                strategy
                    .initialize(initial_capital, Default::default())
                    .await
                    .unwrap();

                // Create synthetic market event
                let symbol = Symbol::new("BTCUSD".to_string());
                let price = Price::from_f64(50000.0)
                    .map_err(|e| format!("Failed to create benchmark price: {}", e))
                    .unwrap();
                let size = Quantity::from_f64(1.0)
                    .map_err(|e| format!("Failed to create benchmark quantity: {}", e))
                    .unwrap();
                let timestamp = Utc::now();

                let market_event = MarketEvent::Trade {
                    symbol: symbol.clone(),
                    price,
                    size,
                    timestamp,
                    side: None,
                    venue: None,
                    trade_id: None,
                };

                // Create strategy context
                let positions = HashMap::new();
                let open_orders = HashMap::new();
                let mut market_prices = HashMap::new();
                market_prices.insert(symbol.clone(), price);

                let context = StrategyContext {
                    current_time: timestamp,
                    account_balance: initial_capital,
                    buying_power: initial_capital,
                    positions,
                    open_orders,
                    market_prices,
                    performance: Default::default(),
                };

                // CRITICAL MEASUREMENT: Market event to trading signal
                let start = Instant::now();
                let signals = strategy
                    .on_market_event(&market_event, &context)
                    .await
                    .unwrap();
                let latency = start.elapsed();

                black_box((signals, latency));

                // Validate sub-50μs target
                if latency > Duration::from_micros(50) {
                    eprintln!(
                        "WARNING: Latency {}μs exceeds 50μs target",
                        latency.as_micros()
                    );
                }

                latency
            })
        });
    });
}

/// Benchmark feature extraction performance (simulated)
fn bench_feature_extraction(c: &mut Criterion) {
    let rt = tokio::runtime::Runtime::new().unwrap();

    let mut group = c.benchmark_group("feature_extraction");

    for data_points in &[10, 50, 100, 500] {
        group.bench_with_input(
            BenchmarkId::new("data_points", data_points),
            data_points,
            |b, &data_points| {
                b.iter(|| {
                    rt.block_on(async {
                        // Simulate feature extraction by calculating statistics
                        // over synthetic price data
                        let mut prices = Vec::new();
                        for i in 0..data_points {
                            prices.push(Decimal::from(50000 + i * 10));
                        }

                        // Benchmark simulated feature extraction
                        let start = Instant::now();

                        // Simulate feature calculations
                        let _mean = prices.iter().sum::<Decimal>() / Decimal::from(prices.len());
                        let _max = prices.iter().max().copied().unwrap_or(Decimal::ZERO);
                        let _min = prices.iter().min().copied().unwrap_or(Decimal::ZERO);

                        let latency = start.elapsed();

                        black_box(latency);
                        latency
                    })
                });
            },
        );
    }

    group.finish();
}

/// Benchmark SIMD vs scalar mathematical operations
fn bench_simd_operations(c: &mut Criterion) {
    let mut group = c.benchmark_group("simd_operations");

    // Generate test data
    let prices: Vec<f64> = (0..1000).map(|i| 50000.0 + i as f64 * 0.1).collect();

    group.bench_function("scalar_returns", |b| {
        b.iter(|| {
            // Simulate scalar returns calculation
            let returns: Vec<f64> = prices
                .windows(2)
                .map(|window| (window[1] - window[0]) / window[0])
                .collect();
            black_box(returns);
        });
    });

    group.bench_function("vectorized_operations", |b| {
        b.iter(|| {
            // Test AVX2 vectorized operations
            #[cfg(target_arch = "x86_64")]
            {
                if std::arch::is_x86_feature_detected!("avx2") {
                    // Simulated SIMD calculation (actual implementation in strategy_runner)
                    let mut results = Vec::with_capacity(prices.len() - 1);
                    for chunk in prices.chunks_exact(4) {
                        if chunk.len() >= 2 {
                            for i in 0..chunk.len() - 1 {
                                results.push((chunk[i + 1] - chunk[i]) / chunk[i]);
                            }
                        }
                    }
                    black_box(results);
                } else {
                    // Fallback scalar
                    let returns: Vec<f64> = prices
                        .windows(2)
                        .map(|window| (window[1] - window[0]) / window[0])
                        .collect();
                    black_box(returns);
                }
            }

            #[cfg(not(target_arch = "x86_64"))]
            {
                let returns: Vec<f64> = prices
                    .windows(2)
                    .map(|window| (window[1] - window[0]) / window[0])
                    .collect();
                black_box(returns);
            }
        });
    });

    group.finish();
}

/// Benchmark parallel vs sequential model execution
fn bench_model_execution(c: &mut Criterion) {
    let rt = tokio::runtime::Runtime::new().unwrap();

    let mut group = c.benchmark_group("model_execution");

    group.bench_function("sequential_models", |b| {
        b.iter(|| {
            rt.block_on(async {
                // Simulate sequential model calls
                let start = Instant::now();
                for _model in 0..5 {
                    // Simulate 10μs model inference time
                    tokio::time::sleep(Duration::from_micros(10)).await;
                }
                let latency = start.elapsed();
                black_box(latency);
                latency
            })
        });
    });

    group.bench_function("parallel_models", |b| {
        b.iter(|| {
            rt.block_on(async {
                // Simulate parallel model calls
                let start = Instant::now();
                let futures: Vec<_> = (0..5)
                    .map(|_| async {
                        // Simulate 10μs model inference time
                        tokio::time::sleep(Duration::from_micros(10)).await;
                    })
                    .collect();
                futures::future::join_all(futures).await;
                let latency = start.elapsed();
                black_box(latency);
                latency
            })
        });
    });

    group.finish();
}

/// Comprehensive HFT performance validation
fn bench_hft_comprehensive(c: &mut Criterion) {
    let rt = tokio::runtime::Runtime::new().unwrap();

    c.bench_function("hft_end_to_end", |b| {
        b.iter(|| {
            rt.block_on(async {
                let start = Instant::now();

                // 1. Market data ingestion (simulated)
                let ingestion_time = Duration::from_nanos(500); // Target: <1μs

                // 2. Feature extraction (optimized)
                let feature_time = Duration::from_micros(5); // Target: <5μs

                // 3. Model inference (parallel)
                let model_time = Duration::from_micros(15); // Target: <15μs

                // 4. Risk checks (optimized)
                let risk_time = Duration::from_micros(2); // Target: <2μs

                // 5. Order generation (optimized)
                let order_time = Duration::from_micros(1); // Target: <1μs

                let total_simulated =
                    ingestion_time + feature_time + model_time + risk_time + order_time;

                // Actual sleep to simulate work
                tokio::time::sleep(total_simulated).await;

                let actual_latency = start.elapsed();

                black_box(actual_latency);

                // Validate against targets
                assert!(
                    actual_latency < Duration::from_micros(50),
                    "End-to-end latency {}μs exceeds 50μs target",
                    actual_latency.as_micros()
                );

                actual_latency
            })
        });
    });
}

criterion_group!(
    benches,
    bench_market_event_latency,
    bench_feature_extraction,
    bench_simd_operations,
    bench_model_execution,
    bench_hft_comprehensive
);

criterion_main!(benches);
