#![allow(dead_code)]
//! Throughput Benchmark - Concurrent Authenticated Requests
//!
//! Measures maximum requests per second:
//! - TARGET: >100,000 req/s single-threaded
//! - Multi-threaded scaling
//! - Different authentication workloads
//! - Realistic traffic patterns

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

/// Lightweight auth simulator
struct AuthSimulator {
    success_rate: f64,
    counter: Arc<AtomicU64>,
}

impl AuthSimulator {
    fn new(success_rate: f64) -> Self {
        Self {
            success_rate,
            counter: Arc::new(AtomicU64::new(0)),
        }
    }

    async fn authenticate(&self, _request_id: u64) -> bool {
        let count = self.counter.fetch_add(1, Ordering::Relaxed);
        // Simulate success rate
        (count as f64 / 100.0) % 1.0 < self.success_rate
    }

    fn requests_processed(&self) -> u64 {
        self.counter.load(Ordering::Relaxed)
    }
}

/// Request handler
struct RequestHandler {
    auth: Arc<AuthSimulator>,
}

impl RequestHandler {
    fn new(auth: Arc<AuthSimulator>) -> Self {
        Self { auth }
    }

    async fn handle_request(&self, request_id: u64) -> bool {
        self.auth.authenticate(request_id).await
    }
}

/// Benchmark 1: Single-threaded throughput (TARGET: >100K req/s)
fn bench_single_threaded_throughput(c: &mut Criterion) {
    let rt = Runtime::new().unwrap();
    let auth = Arc::new(AuthSimulator::new(0.95)); // 95% success rate
    let handler = RequestHandler::new(auth.clone());

    let mut group = c.benchmark_group("single_threaded_throughput");
    group.throughput(Throughput::Elements(1));

    group.bench_function("100k_req_target", |b| {
        b.iter_custom(|iters| {
            let start = Instant::now();
            rt.block_on(async {
                for i in 0..iters {
                    black_box(handler.handle_request(i).await);
                }
            });
            start.elapsed()
        });
    });

    group.finish();
}

/// Benchmark 2: Multi-threaded throughput
fn bench_multi_threaded_throughput(c: &mut Criterion) {
    let mut group = c.benchmark_group("multi_threaded_throughput");

    for num_threads in &[1, 2, 4, 8, 16] {
        let rt = tokio::runtime::Builder::new_multi_thread()
            .worker_threads(*num_threads)
            .build()
            .unwrap();

        let auth = Arc::new(AuthSimulator::new(0.95));
        let handler = Arc::new(RequestHandler::new(auth.clone()));

        group.throughput(Throughput::Elements(1000));

        group.bench_with_input(
            BenchmarkId::new("concurrent_requests", num_threads),
            num_threads,
            |b, &threads| {
                b.iter_custom(|iters| {
                    let start = Instant::now();
                    rt.block_on(async {
                        let mut handles = vec![];
                        let requests_per_thread = iters / threads as u64;

                        for _ in 0..threads {
                            let handler_clone = handler.clone();
                            let handle = tokio::spawn(async move {
                                for i in 0..requests_per_thread {
                                    black_box(handler_clone.handle_request(i).await);
                                }
                            });
                            handles.push(handle);
                        }

                        for handle in handles {
                            handle.await.unwrap();
                        }
                    });
                    start.elapsed()
                });
            },
        );
    }

    group.finish();
}

/// Benchmark 3: Different success rates
fn bench_success_rate_impact(c: &mut Criterion) {
    let rt = Runtime::new().unwrap();
    let mut group = c.benchmark_group("success_rate_impact");

    for success_rate in &[0.5, 0.8, 0.95, 0.99, 1.0] {
        let auth = Arc::new(AuthSimulator::new(*success_rate));
        let handler = RequestHandler::new(auth.clone());

        group.throughput(Throughput::Elements(1000));

        group.bench_with_input(
            BenchmarkId::new("throughput", format!("{}%", (success_rate * 100.0) as u32)),
            success_rate,
            |b, _rate| {
                b.iter_custom(|iters| {
                    let start = Instant::now();
                    rt.block_on(async {
                        for i in 0..iters {
                            black_box(handler.handle_request(i).await);
                        }
                    });
                    start.elapsed()
                });
            },
        );
    }

    group.finish();
}

/// Benchmark 4: Burst traffic patterns
fn bench_burst_patterns(c: &mut Criterion) {
    let rt = Runtime::new().unwrap();
    let auth = Arc::new(AuthSimulator::new(0.95));
    let handler = Arc::new(RequestHandler::new(auth.clone()));

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

    // Constant load
    group.bench_function("constant_load_1000_req", |b| {
        b.iter_custom(|iters| {
            let start = Instant::now();
            rt.block_on(async {
                for i in 0..iters.min(1000) {
                    black_box(handler.handle_request(i).await);
                }
            });
            start.elapsed()
        });
    });

    // Burst pattern: All at once
    group.bench_function("burst_1000_concurrent", |b| {
        b.iter_custom(|iters| {
            let start = Instant::now();
            rt.block_on(async {
                let mut handles = vec![];
                for i in 0..iters.min(1000) {
                    let handler_clone = handler.clone();
                    let handle = tokio::spawn(async move { handler_clone.handle_request(i).await });
                    handles.push(handle);
                }
                for handle in handles {
                    black_box(handle.await.unwrap());
                }
            });
            start.elapsed()
        });
    });

    group.finish();
}

/// Benchmark 5: Request size impact on throughput
fn bench_request_size_throughput(c: &mut Criterion) {
    let rt = Runtime::new().unwrap();

    struct RequestProcessor {
        auth: Arc<AuthSimulator>,
    }

    impl RequestProcessor {
        async fn process(&self, _data: &[u8]) -> bool {
            self.auth.authenticate(0).await
        }
    }

    let auth = Arc::new(AuthSimulator::new(0.95));
    let processor = RequestProcessor { auth: auth.clone() };

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

    for size in &[100, 1_000, 10_000, 100_000] {
        let data = vec![0u8; *size];

        group.throughput(Throughput::Bytes(*size as u64));

        group.bench_with_input(
            BenchmarkId::new("process_request", format!("{}B", size)),
            &data,
            |b, request_data| {
                b.iter_custom(|iters| {
                    let start = Instant::now();
                    rt.block_on(async {
                        for _ in 0..iters {
                            black_box(processor.process(request_data).await);
                        }
                    });
                    start.elapsed()
                });
            },
        );
    }

    group.finish();
}

/// Benchmark 6: Sustained throughput over time
fn bench_sustained_throughput(c: &mut Criterion) {
    let rt = Runtime::new().unwrap();
    let auth = Arc::new(AuthSimulator::new(0.95));
    let handler = RequestHandler::new(auth.clone());

    c.bench_function("sustained_1_second", |b| {
        b.iter_custom(|_iters| {
            let start = Instant::now();
            let mut count = 0u64;

            rt.block_on(async {
                let end_time = Instant::now() + Duration::from_secs(1);
                while Instant::now() < end_time {
                    black_box(handler.handle_request(count).await);
                    count += 1;
                }
            });

            let elapsed = start.elapsed();
            let rps = count as f64 / elapsed.as_secs_f64();
            println!("Sustained throughput: {:.0} req/s", rps);
            elapsed
        });
    });
}

/// Benchmark 7: Request rate limits
fn bench_rate_limited_throughput(c: &mut Criterion) {
    let rt = Runtime::new().unwrap();

    struct RateLimitedHandler {
        auth: Arc<AuthSimulator>,
        limit: AtomicU64,
        max_rps: u64,
    }

    impl RateLimitedHandler {
        fn new(auth: Arc<AuthSimulator>, max_rps: u64) -> Self {
            Self {
                auth,
                limit: AtomicU64::new(0),
                max_rps,
            }
        }

        async fn handle(&self, request_id: u64) -> bool {
            let count = self.limit.fetch_add(1, Ordering::Relaxed);
            if count >= self.max_rps {
                return false; // Rate limited
            }
            self.auth.authenticate(request_id).await
        }
    }

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

    for limit in &[1_000, 10_000, 100_000] {
        let auth = Arc::new(AuthSimulator::new(0.95));
        let handler = RateLimitedHandler::new(auth.clone(), *limit);

        group.bench_with_input(BenchmarkId::new("max_rps", limit), limit, |b, _| {
            b.iter_custom(|iters| {
                let start = Instant::now();
                rt.block_on(async {
                    for i in 0..iters {
                        black_box(handler.handle(i).await);
                    }
                });
                start.elapsed()
            });
        });
    }

    group.finish();
}

/// Benchmark 8: HFT scenario (TARGET: 100K req/s minimum)
fn bench_hft_scenario(c: &mut Criterion) {
    let rt = Runtime::new().unwrap();
    let auth = Arc::new(AuthSimulator::new(0.99)); // 99% success (HFT quality)
    let handler = RequestHandler::new(auth.clone());

    let mut group = c.benchmark_group("hft_scenario");
    group.throughput(Throughput::Elements(100_000));

    group.bench_function("hft_100k_target", |b| {
        b.iter_custom(|iters| {
            let start = Instant::now();
            rt.block_on(async {
                for i in 0..iters {
                    black_box(handler.handle_request(i).await);
                }
            });
            let elapsed = start.elapsed();

            // Calculate actual throughput
            let rps = iters as f64 / elapsed.as_secs_f64();
            if rps < 100_000.0 {
                println!("⚠️  Below target: {:.0} req/s (target: 100K)", rps);
            } else {
                println!("✓ Target met: {:.0} req/s", rps);
            }

            elapsed
        });
    });

    group.finish();
}

/// Benchmark 9: Latency under load
fn bench_latency_under_load(c: &mut Criterion) {
    let rt = Runtime::new().unwrap();
    let auth = Arc::new(AuthSimulator::new(0.95));
    let handler = Arc::new(RequestHandler::new(auth.clone()));

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

    for load in &[100, 1_000, 10_000, 100_000] {
        group.bench_with_input(
            BenchmarkId::new("requests_in_flight", load),
            load,
            |b, &n| {
                b.iter_custom(|_iters| {
                    let start = Instant::now();
                    rt.block_on(async {
                        let mut handles = vec![];
                        for i in 0..n {
                            let handler_clone = handler.clone();
                            let handle =
                                tokio::spawn(async move { handler_clone.handle_request(i).await });
                            handles.push(handle);
                        }
                        for handle in handles {
                            black_box(handle.await.unwrap());
                        }
                    });
                    start.elapsed()
                });
            },
        );
    }

    group.finish();
}

/// Benchmark 10: Request batching efficiency
fn bench_batching_efficiency(c: &mut Criterion) {
    let rt = Runtime::new().unwrap();
    let auth = Arc::new(AuthSimulator::new(0.95));
    let handler = Arc::new(RequestHandler::new(auth.clone()));

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

    for batch_size in &[1, 10, 100, 1000] {
        group.throughput(Throughput::Elements(*batch_size as u64));

        group.bench_with_input(
            BenchmarkId::new("batch_processing", batch_size),
            batch_size,
            |b, &n| {
                b.iter_custom(|iters| {
                    let start = Instant::now();
                    rt.block_on(async {
                        for batch in 0..(iters / n as u64) {
                            let mut handles = vec![];
                            for i in 0..n {
                                let handler_clone = handler.clone();
                                let request_id = batch * n as u64 + i as u64;
                                let handle = tokio::spawn(async move {
                                    handler_clone.handle_request(request_id).await
                                });
                                handles.push(handle);
                            }
                            for handle in handles {
                                black_box(handle.await.unwrap());
                            }
                        }
                    });
                    start.elapsed()
                });
            },
        );
    }

    group.finish();
}

criterion_group!(
    throughput_benches,
    bench_single_threaded_throughput,
    bench_multi_threaded_throughput,
    bench_success_rate_impact,
    bench_burst_patterns,
    bench_request_size_throughput,
    bench_sustained_throughput,
    bench_rate_limited_throughput,
    bench_hft_scenario,
    bench_latency_under_load,
    bench_batching_efficiency
);

criterion_main!(throughput_benches);
