//! Streaming load test: 1M concurrent market data updates

use anyhow::Result;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
use tokio::task::JoinSet;

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

pub async fn run(url: &str) -> Result<crate::metrics::LoadTestReport> {
    const NUM_STREAMS: usize = 1000;
    const UPDATES_PER_STREAM: usize = 1000;
    const DURATION_SECS: u64 = 30;

    tracing::info!(
        "Starting Market Data Streaming: 1M updates across {} streams",
        NUM_STREAMS
    );

    let metrics = Arc::new(LoadTestMetrics::new());
    let update_count = Arc::new(AtomicUsize::new(0));
    let mut join_set = JoinSet::new();

    for stream_id in 0..NUM_STREAMS {
        let url = url.to_string();
        let metrics = Arc::clone(&metrics);
        let update_count = Arc::clone(&update_count);

        join_set.spawn(async move {
            let mut client = TradingClient::connect(&url).await?;
            client
                .run_streaming_workload(
                    stream_id,
                    DURATION_SECS,
                    UPDATES_PER_STREAM,
                    &metrics,
                    &update_count,
                )
                .await
        });
    }

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

    let total_updates = update_count.load(Ordering::Relaxed);
    tracing::info!("Total market data updates received: {}", total_updates);

    let mut report = metrics.to_report("Market Data Streaming: 1M updates");
    report.add_custom_metric("total_updates", total_updates as f64);

    Ok(report)
}
