//! Connection pool saturation test: 1000 concurrent clients

use anyhow::Result;
use std::sync::Arc;
use std::time::Duration;
use tokio::sync::Barrier;
use tokio::task::JoinSet;

use crate::clients::TradingClient;
use crate::metrics::LoadTestMetrics;

pub async fn run(url: &str) -> Result<crate::metrics::LoadTestReport> {
    const NUM_CLIENTS: usize = 1000;
    const REQUESTS_PER_CLIENT: usize = 100;

    tracing::info!(
        "Starting Connection Pool Saturation: {} concurrent clients",
        NUM_CLIENTS
    );

    let metrics = Arc::new(LoadTestMetrics::new());
    let barrier = Arc::new(Barrier::new(NUM_CLIENTS));
    let mut join_set = JoinSet::new();

    for client_id in 0..NUM_CLIENTS {
        let url = url.to_string();
        let metrics = Arc::clone(&metrics);
        let barrier = Arc::clone(&barrier);

        join_set.spawn(async move {
            // Connect and measure connection time
            let connect_start = std::time::Instant::now();
            let mut client = match TradingClient::connect(&url).await {
                Ok(c) => {
                    metrics.record_request(connect_start.elapsed(), true);
                    c
                },
                Err(e) => {
                    tracing::error!("Client {} connection failed: {:?}", client_id, e);
                    metrics.record_request(connect_start.elapsed(), false);
                    return Ok::<_, anyhow::Error>(());
                },
            };

            // Wait for all clients to connect
            barrier.wait().await;

            // Submit requests
            for req_id in 0..REQUESTS_PER_CLIENT {
                match client.submit_test_order(client_id, req_id).await {
                    Ok(duration) => metrics.record_request(duration, true),
                    Err(e) => {
                        tracing::warn!("Client {} request {} failed: {:?}", client_id, req_id, e);
                        metrics.record_request(Duration::from_micros(0), false);
                    },
                }

                tokio::time::sleep(Duration::from_millis(10)).await;
            }

            Ok::<_, anyhow::Error>(())
        });
    }

    // Wait for all clients
    while let Some(result) = join_set.join_next().await {
        if let Err(e) = result {
            tracing::error!("Pool saturation client failed: {:?}", e);
        }
    }

    Ok(metrics.to_report("Connection Pool Saturation: 1000 clients"))
}
