#![allow(
    clippy::unwrap_used,
    clippy::expect_used,
    clippy::indexing_slicing,
    clippy::str_to_string,
    clippy::string_to_string,
    clippy::shadow_unrelated,
    clippy::shadow_reuse,
    clippy::similar_names,
    clippy::non_ascii_literal,
    clippy::doc_markdown,
    clippy::integer_division,
    clippy::manual_range_contains,
    clippy::useless_format,
    clippy::clone_on_copy,
    clippy::missing_const_for_fn,
    unused_imports,
    unused_variables,
    dead_code,
)]
//! End-to-End Trading Performance Benchmarks
//!
//! Comprehensive benchmarking of complete order lifecycle:
//! 1. Order Lifecycle: Submit → Order manager → Trading engine (P99 < 100μs)
//! 2. Execution Pipeline: Execute → Update position → Validate risk (P99 < 50μs)
//! 3. Settlement: Calculate PnL → Log compliance → Update portfolio (P99 < 75μs)
//!
//! **Performance Targets**:
//! - P99 Latency: < 100μs (order lifecycle)
//! - Throughput: > 100K orders/sec
//! - Memory: < 100MB per 1M orders
//!
//! **Measurement Strategy**:
//! - Uses criterion for statistical benchmarking
//! - HDR Histogram for latency distribution
//! - Memory profiling for allocation tracking
//! - Component breakdown for bottleneck identification

use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion, Throughput};
use hdrhistogram::Histogram;
use std::sync::Arc;
use std::time::{Duration, Instant};
use tokio::runtime::Runtime;

// Trading engine imports
use common::{OrderSide, OrderStatus, OrderType, TimeInForce};
use rust_decimal::Decimal;
use std::collections::HashMap;
use trading_engine::trading_operations::{
    ExecutionResult, LiquidityFlag, TradingOperations, TradingOrder,
};

/// Performance metrics collector for E2E benchmarking
struct PerformanceMetrics {
    histogram: Histogram<u64>,
    order_count: u64,
    total_latency_ns: u64,
    memory_baseline_kb: usize,
}

impl PerformanceMetrics {
    fn new() -> Self {
        Self {
            histogram: Histogram::<u64>::new(3).unwrap(),
            order_count: 0,
            total_latency_ns: 0,
            memory_baseline_kb: Self::current_memory_kb(),
        }
    }

    fn record_latency(&mut self, latency: Duration) {
        let nanos = latency.as_nanos() as u64;
        self.histogram.record(nanos / 1000).ok(); // Convert to microseconds
        self.order_count += 1;
        self.total_latency_ns += nanos;
    }

    fn report(&self, label: &str) {
        let p50 = self.histogram.value_at_percentile(50.0) as f64;
        let p95 = self.histogram.value_at_percentile(95.0) as f64;
        let p99 = self.histogram.value_at_percentile(99.0) as f64;
        let max = self.histogram.max() as f64;
        let avg = (self.total_latency_ns as f64 / self.order_count as f64) / 1000.0;

        let memory_delta_kb = Self::current_memory_kb() - self.memory_baseline_kb;
        let memory_per_order_bytes = (memory_delta_kb * 1024) / self.order_count as usize;

        println!("\n=== {} ===", label);
        println!("Orders: {}", self.order_count);
        println!("Latency Percentiles:");
        println!("  P50:  {:.2}μs", p50);
        println!("  P95:  {:.2}μs", p95);
        println!("  P99:  {:.2}μs", p99);
        println!("  Max:  {:.2}μs", max);
        println!("  Avg:  {:.2}μs", avg);
        println!("Memory:");
        println!("  Delta: {}KB", memory_delta_kb);
        println!("  Per Order: {}B", memory_per_order_bytes);

        // Check targets
        if p99 < 100.0 {
            println!("✅ P99 TARGET MET: {:.2}μs < 100μs", p99);
        } else {
            println!("❌ P99 TARGET MISSED: {:.2}μs >= 100μs", p99);
        }

        if memory_per_order_bytes < 100 {
            println!(
                "✅ MEMORY TARGET MET: {}B < 100B/order",
                memory_per_order_bytes
            );
        } else {
            println!(
                "⚠️  MEMORY TARGET EXCEEDED: {}B >= 100B/order",
                memory_per_order_bytes
            );
        }
    }

    fn current_memory_kb() -> usize {
        // Simple memory estimation - in production use jemalloc stats
        #[cfg(target_os = "linux")]
        {
            if let Ok(status) = std::fs::read_to_string("/proc/self/status") {
                for line in status.lines() {
                    if line.starts_with("VmRSS:") {
                        if let Some(kb_str) = line.split_whitespace().nth(1) {
                            return kb_str.parse().unwrap_or(0);
                        }
                    }
                }
            }
        }
        0
    }
}

/// Create a sample order for benchmarking
fn create_test_order(id: u64) -> TradingOrder {
    TradingOrder {
        id: common::OrderId::new(),
        symbol: format!("TEST{}", id % 100), // Simulate 100 different symbols
        side: if id % 2 == 0 {
            OrderSide::Buy
        } else {
            OrderSide::Sell
        },
        order_type: OrderType::Limit,
        quantity: Decimal::new(100 + (id % 1000) as i64, 0),
        price: Decimal::new(15000 + (id % 5000) as i64, 2),
        time_in_force: TimeInForce::Day,
        account_id: Some(format!("ACC{}", id % 10)),
        metadata: HashMap::new(),
        created_at: chrono::Utc::now(),
        submitted_at: None,
        executed_at: None,
        status: OrderStatus::Created,
        fill_quantity: Decimal::ZERO,
        average_fill_price: None,
    }
}

/// Create a sample execution result for benchmarking
fn create_test_execution(order_id: u64) -> ExecutionResult {
    ExecutionResult {
        order_id: common::OrderId::new(),
        symbol: format!("TEST{}", order_id % 100),
        side: common::OrderSide::Buy,
        executed_quantity: Decimal::new(100, 0),
        execution_price: Decimal::new(15000, 2),
        execution_time: chrono::Utc::now(),
        commission: Decimal::new(1, 0),
        liquidity_flag: LiquidityFlag::Taker,
    }
}

//
// ==================== BENCHMARK 1: ORDER LIFECYCLE ====================
//

/// Benchmark 1a: Single order submission (baseline)
fn bench_order_submission_single(c: &mut Criterion) {
    let rt = Runtime::new().unwrap();
    let trading_ops = Arc::new(TradingOperations::new());

    c.bench_function("e2e/order_lifecycle/single_submit", |b| {
        b.iter_custom(|iters| {
            let start = Instant::now();
            rt.block_on(async {
                for i in 0..iters {
                    let order = create_test_order(i);
                    black_box(trading_ops.submit_order(order).await).ok();
                }
            });
            start.elapsed()
        });
    });
}

/// Benchmark 1b: Batch order submission
fn bench_order_submission_batch(c: &mut Criterion) {
    let mut group = c.benchmark_group("e2e/order_lifecycle/batch_submit");

    for batch_size in &[10, 100, 1000] {
        let rt = Runtime::new().unwrap();
        let trading_ops = Arc::new(TradingOperations::new());

        group.throughput(Throughput::Elements(*batch_size as u64));
        group.bench_with_input(
            BenchmarkId::from_parameter(batch_size),
            batch_size,
            |b, &size| {
                b.iter_custom(|_iters| {
                    let start = Instant::now();
                    rt.block_on(async {
                        for i in 0..size {
                            let order = create_test_order(i as u64);
                            black_box(trading_ops.submit_order(order).await).ok();
                        }
                    });
                    start.elapsed()
                });
            },
        );
    }

    group.finish();
}

/// Benchmark 1c: Order lifecycle with latency distribution
fn bench_order_lifecycle_distribution(c: &mut Criterion) {
    let rt = Runtime::new().unwrap();
    let trading_ops = Arc::new(TradingOperations::new());

    c.bench_function("e2e/order_lifecycle/latency_distribution", |b| {
        b.iter_custom(|iters| {
            let mut metrics = PerformanceMetrics::new();

            rt.block_on(async {
                for i in 0..iters {
                    let order = create_test_order(i);
                    let start = Instant::now();
                    black_box(trading_ops.submit_order(order).await).ok();
                    metrics.record_latency(start.elapsed());
                }
            });

            metrics.report("Order Lifecycle - Submit to Tracking");
            Duration::from_nanos(metrics.total_latency_ns / iters.max(1))
        });
    });
}

//
// ==================== BENCHMARK 2: EXECUTION PIPELINE ====================
//

/// Benchmark 2a: Order execution processing
fn bench_execution_processing(c: &mut Criterion) {
    let rt = Runtime::new().unwrap();
    let trading_ops = Arc::new(TradingOperations::new());

    c.bench_function("e2e/execution_pipeline/process_execution", |b| {
        b.iter_custom(|iters| {
            let start = Instant::now();
            rt.block_on(async {
                for i in 0..iters {
                    let execution = create_test_execution(i);
                    black_box(trading_ops.process_execution(execution).await).ok();
                }
            });
            start.elapsed()
        });
    });
}

/// Benchmark 2b: Execution pipeline with position updates
fn bench_execution_with_position_update(c: &mut Criterion) {
    let rt = Runtime::new().unwrap();
    let trading_ops = Arc::new(TradingOperations::new());

    c.bench_function("e2e/execution_pipeline/with_position_update", |b| {
        b.iter_custom(|iters| {
            let mut metrics = PerformanceMetrics::new();

            rt.block_on(async {
                for i in 0..iters {
                    let start = Instant::now();

                    // Step 1: Execute order
                    let execution = create_test_execution(i);
                    black_box(trading_ops.process_execution(execution).await).ok();

                    // Step 2: Update position (simulated)
                    tokio::time::sleep(Duration::from_nanos(100)).await;

                    // Step 3: Risk validation (simulated)
                    tokio::time::sleep(Duration::from_nanos(50)).await;

                    metrics.record_latency(start.elapsed());
                }
            });

            metrics.report("Execution Pipeline - Full Flow");
            Duration::from_nanos(metrics.total_latency_ns / iters.max(1))
        });
    });
}

/// Benchmark 2c: Concurrent execution processing
fn bench_execution_concurrent(c: &mut Criterion) {
    let mut group = c.benchmark_group("e2e/execution_pipeline/concurrent");

    for concurrency in &[10, 100, 1000] {
        let rt = Runtime::new().unwrap();
        let trading_ops = Arc::new(TradingOperations::new());

        group.throughput(Throughput::Elements(*concurrency as u64));
        group.bench_with_input(
            BenchmarkId::from_parameter(concurrency),
            concurrency,
            |b, &n| {
                b.iter_custom(|_iters| {
                    let start = Instant::now();
                    rt.block_on(async {
                        let mut handles = vec![];
                        for i in 0..n {
                            let ops = trading_ops.clone();
                            let handle = tokio::spawn(async move {
                                let execution = create_test_execution(i as u64);
                                ops.process_execution(execution).await
                            });
                            handles.push(handle);
                        }
                        for handle in handles {
                            black_box(handle.await.ok());
                        }
                    });
                    start.elapsed()
                });
            },
        );
    }

    group.finish();
}

//
// ==================== BENCHMARK 3: SETTLEMENT FLOW ====================
//

/// Benchmark 3a: PnL calculation
fn bench_pnl_calculation(c: &mut Criterion) {
    let rt = Runtime::new().unwrap();
    let trading_ops = Arc::new(TradingOperations::new());

    c.bench_function("e2e/settlement/pnl_calculation", |b| {
        b.iter_custom(|iters| {
            let start = Instant::now();
            rt.block_on(async {
                for i in 0..iters {
                    let execution = create_test_execution(i);
                    // PnL calculation is internal to process_execution
                    black_box(trading_ops.process_execution(execution).await).ok();
                }
            });
            start.elapsed()
        });
    });
}

/// Benchmark 3b: Full settlement flow (PnL + Compliance + Portfolio)
fn bench_settlement_full_flow(c: &mut Criterion) {
    let rt = Runtime::new().unwrap();
    let trading_ops = Arc::new(TradingOperations::new());

    c.bench_function("e2e/settlement/full_flow", |b| {
        b.iter_custom(|iters| {
            let mut metrics = PerformanceMetrics::new();

            rt.block_on(async {
                for i in 0..iters {
                    let start = Instant::now();

                    // Step 1: Calculate PnL
                    let execution = create_test_execution(i);
                    black_box(trading_ops.process_execution(execution).await).ok();

                    // Step 2: Log compliance (simulated database write)
                    tokio::time::sleep(Duration::from_micros(5)).await;

                    // Step 3: Update portfolio (simulated)
                    tokio::time::sleep(Duration::from_nanos(500)).await;

                    metrics.record_latency(start.elapsed());
                }
            });

            metrics.report("Settlement - Full Flow (PnL + Compliance + Portfolio)");
            Duration::from_nanos(metrics.total_latency_ns / iters.max(1))
        });
    });
}

/// Benchmark 3c: Settlement batch processing
fn bench_settlement_batch(c: &mut Criterion) {
    let mut group = c.benchmark_group("e2e/settlement/batch");

    for batch_size in &[100, 1000, 10000] {
        let rt = Runtime::new().unwrap();
        let trading_ops = Arc::new(TradingOperations::new());

        group.throughput(Throughput::Elements(*batch_size as u64));
        group.bench_with_input(
            BenchmarkId::from_parameter(batch_size),
            batch_size,
            |b, &size| {
                b.iter_custom(|_iters| {
                    let start = Instant::now();
                    rt.block_on(async {
                        for i in 0..size {
                            let execution = create_test_execution(i as u64);
                            black_box(trading_ops.process_execution(execution).await).ok();
                        }
                    });
                    start.elapsed()
                });
            },
        );
    }

    group.finish();
}

//
// ==================== BENCHMARK 4: THROUGHPUT TESTS ====================
//

/// Benchmark 4a: Sustained throughput (1 second test)
fn bench_sustained_throughput(c: &mut Criterion) {
    let rt = Runtime::new().unwrap();
    let trading_ops = Arc::new(TradingOperations::new());

    c.bench_function("e2e/throughput/sustained_1sec", |b| {
        b.iter_custom(|_iters| {
            let start = Instant::now();
            let mut count = 0_u64;

            rt.block_on(async {
                let end_time = Instant::now() + Duration::from_secs(1);
                while Instant::now() < end_time {
                    let order = create_test_order(count);
                    black_box(trading_ops.submit_order(order).await).ok();
                    count += 1;
                }
            });

            let elapsed = start.elapsed();
            let throughput = count as f64 / elapsed.as_secs_f64();

            println!("\n=== Sustained Throughput ===");
            println!("Duration: {:.2}s", elapsed.as_secs_f64());
            println!("Orders: {}", count);
            println!("Throughput: {:.0} orders/sec", throughput);

            if throughput > 100_000.0 {
                println!(
                    "✅ THROUGHPUT TARGET MET: {:.0} > 100K orders/sec",
                    throughput
                );
            } else {
                println!(
                    "❌ THROUGHPUT TARGET MISSED: {:.0} < 100K orders/sec",
                    throughput
                );
            }

            elapsed
        });
    });
}

/// Benchmark 4b: Burst handling
fn bench_burst_handling(c: &mut Criterion) {
    let mut group = c.benchmark_group("e2e/throughput/burst");

    for burst_size in &[1000, 10000, 100000] {
        let rt = Runtime::new().unwrap();
        let trading_ops = Arc::new(TradingOperations::new());

        group.throughput(Throughput::Elements(*burst_size as u64));
        group.bench_with_input(
            BenchmarkId::from_parameter(burst_size),
            burst_size,
            |b, &size| {
                b.iter_custom(|_iters| {
                    let start = Instant::now();
                    rt.block_on(async {
                        let mut handles = vec![];

                        // Fire burst of orders
                        for i in 0..size {
                            let ops = trading_ops.clone();
                            let handle = tokio::spawn(async move {
                                let order = create_test_order(i as u64);
                                ops.submit_order(order).await
                            });
                            handles.push(handle);
                        }

                        // Wait for completion
                        for handle in handles {
                            black_box(handle.await.ok());
                        }
                    });

                    let elapsed = start.elapsed();
                    let throughput = size as f64 / elapsed.as_secs_f64();

                    println!(
                        "Burst {} orders - {:.0} orders/sec, {:.2}ms total",
                        size,
                        throughput,
                        elapsed.as_millis()
                    );

                    elapsed
                });
            },
        );
    }

    group.finish();
}

//
// ==================== BENCHMARK 5: MEMORY EFFICIENCY ====================
//

/// Benchmark 5a: Memory usage per order
fn bench_memory_per_order(c: &mut Criterion) {
    let rt = Runtime::new().unwrap();
    let trading_ops = Arc::new(TradingOperations::new());

    c.bench_function("e2e/memory/per_order_allocation", |b| {
        b.iter_custom(|_iters| {
            let baseline_kb = PerformanceMetrics::current_memory_kb();
            let order_count = 100_000_u64;

            let start = Instant::now();
            rt.block_on(async {
                for i in 0..order_count {
                    let order = create_test_order(i);
                    black_box(trading_ops.submit_order(order).await).ok();
                }
            });

            let delta_kb = PerformanceMetrics::current_memory_kb() - baseline_kb;
            let bytes_per_order = (delta_kb * 1024) / order_count as usize;

            println!("\n=== Memory Efficiency ===");
            println!("Orders Processed: {}", order_count);
            println!("Memory Delta: {}KB", delta_kb);
            println!("Bytes per Order: {}B", bytes_per_order);
            println!(
                "Memory per 1M Orders: {:.2}MB",
                (bytes_per_order * 1_000_000) as f64 / (1024.0 * 1024.0)
            );

            if bytes_per_order < 100 {
                println!("✅ MEMORY TARGET MET: {}B < 100B/order", bytes_per_order);
            } else {
                println!(
                    "⚠️  MEMORY TARGET EXCEEDED: {}B >= 100B/order",
                    bytes_per_order
                );
            }

            start.elapsed()
        });
    });
}

//
// ==================== BENCHMARK 6: COMPONENT BREAKDOWN ====================
//

/// Benchmark 6: Component-level latency breakdown
fn bench_component_breakdown(c: &mut Criterion) {
    let mut group = c.benchmark_group("e2e/components/breakdown");
    let rt = Runtime::new().unwrap();

    // Component 1: Order creation
    group.bench_function("order_creation", |b| {
        b.iter(|| {
            let order = create_test_order(1);
            black_box(order)
        });
    });

    // Component 2: Order validation (simulated)
    group.bench_function("order_validation", |b| {
        b.iter_custom(|iters| {
            let start = Instant::now();
            rt.block_on(async {
                for _ in 0..iters {
                    tokio::time::sleep(Duration::from_nanos(50)).await;
                }
            });
            start.elapsed()
        });
    });

    // Component 3: Trading operations tracking
    let trading_ops = Arc::new(TradingOperations::new());
    group.bench_function("trading_ops_tracking", |b| {
        b.iter_custom(|iters| {
            let start = Instant::now();
            rt.block_on(async {
                for i in 0..iters {
                    let order = create_test_order(i);
                    black_box(trading_ops.submit_order(order).await).ok();
                }
            });
            start.elapsed()
        });
    });

    // Component 4: Execution processing
    group.bench_function("execution_processing", |b| {
        b.iter_custom(|iters| {
            let start = Instant::now();
            rt.block_on(async {
                for i in 0..iters {
                    let execution = create_test_execution(i);
                    black_box(trading_ops.process_execution(execution).await).ok();
                }
            });
            start.elapsed()
        });
    });

    // Component 5: Position update (simulated)
    group.bench_function("position_update", |b| {
        b.iter_custom(|iters| {
            let start = Instant::now();
            rt.block_on(async {
                for _ in 0..iters {
                    tokio::time::sleep(Duration::from_nanos(100)).await;
                }
            });
            start.elapsed()
        });
    });

    // Component 6: Risk validation (simulated)
    group.bench_function("risk_validation", |b| {
        b.iter_custom(|iters| {
            let start = Instant::now();
            rt.block_on(async {
                for _ in 0..iters {
                    tokio::time::sleep(Duration::from_nanos(50)).await;
                }
            });
            start.elapsed()
        });
    });

    group.finish();
}

//
// ==================== BENCHMARK 7: TARGET VALIDATION ====================
//

/// Benchmark 7: Comprehensive target validation
fn bench_target_validation(c: &mut Criterion) {
    let rt = Runtime::new().unwrap();
    let trading_ops = Arc::new(TradingOperations::new());

    c.bench_function("e2e/targets/comprehensive_validation", |b| {
        b.iter_custom(|iters| {
            let mut lifecycle_metrics = PerformanceMetrics::new();
            let mut execution_metrics = PerformanceMetrics::new();
            let mut settlement_metrics = PerformanceMetrics::new();

            rt.block_on(async {
                for i in 0..iters {
                    // Test 1: Order Lifecycle (Target: P99 < 100μs)
                    let start = Instant::now();
                    let order = create_test_order(i);
                    black_box(trading_ops.submit_order(order).await).ok();
                    lifecycle_metrics.record_latency(start.elapsed());

                    // Test 2: Execution Pipeline (Target: P99 < 50μs)
                    let start = Instant::now();
                    let execution = create_test_execution(i);
                    black_box(trading_ops.process_execution(execution).await).ok();
                    execution_metrics.record_latency(start.elapsed());

                    // Test 3: Settlement (Target: P99 < 75μs)
                    let start = Instant::now();
                    tokio::time::sleep(Duration::from_micros(5)).await; // Compliance logging
                    tokio::time::sleep(Duration::from_nanos(500)).await; // Portfolio update
                    settlement_metrics.record_latency(start.elapsed());
                }
            });

            lifecycle_metrics.report("ORDER LIFECYCLE (Target: P99 < 100μs)");
            execution_metrics.report("EXECUTION PIPELINE (Target: P99 < 50μs)");
            settlement_metrics.report("SETTLEMENT FLOW (Target: P99 < 75μs)");

            // Return average across all flows
            Duration::from_nanos(
                (lifecycle_metrics.total_latency_ns
                    + execution_metrics.total_latency_ns
                    + settlement_metrics.total_latency_ns)
                    / (iters.max(1) * 3),
            )
        });
    });
}

// Criterion benchmark groups
criterion_group!(
    order_lifecycle_benches,
    bench_order_submission_single,
    bench_order_submission_batch,
    bench_order_lifecycle_distribution,
);

criterion_group!(
    execution_pipeline_benches,
    bench_execution_processing,
    bench_execution_with_position_update,
    bench_execution_concurrent,
);

criterion_group!(
    settlement_benches,
    bench_pnl_calculation,
    bench_settlement_full_flow,
    bench_settlement_batch,
);

criterion_group!(
    throughput_benches,
    bench_sustained_throughput,
    bench_burst_handling,
);

criterion_group!(memory_benches, bench_memory_per_order,);

criterion_group!(component_benches, bench_component_breakdown,);

criterion_group!(validation_benches, bench_target_validation,);

criterion_main!(
    order_lifecycle_benches,
    execution_pipeline_benches,
    settlement_benches,
    throughput_benches,
    memory_benches,
    component_benches,
    validation_benches,
);
