//! Market Data Helper for E2E Tests
//!
//! Provides utilities to publish test market data events that can be streamed
//! through the Trading Service's `stream_market_data` endpoint.

use anyhow::Result;
use tokio::time::{interval, Duration};
use tracing::info;

/// Start a background task that publishes test market data events
///
/// This helper publishes periodic market data events to enable E2E tests
/// that depend on market data streaming. Events are published at 10 Hz (100ms intervals).
///
/// # Arguments
/// * `symbols` - List of symbols to generate market data for
/// * `duration_secs` - How long to run the generator (0 = run indefinitely)
///
/// # Returns
/// A handle that can be used to stop the generator
pub fn start_test_market_data_publisher(
    symbols: Vec<String>,
    duration_secs: u64,
) -> tokio::task::JoinHandle<()> {
    info!(
        "🎲 Starting test market data publisher for symbols: {:?}",
        symbols
    );

    tokio::spawn(async move {
        let mut tick = interval(Duration::from_millis(100)); // 10 Hz
        let mut sequence = 0u64;
        let start_time = tokio::time::Instant::now();

        loop {
            // Check if we should stop (duration_secs == 0 means run forever)
            if duration_secs > 0 && start_time.elapsed().as_secs() >= duration_secs {
                info!("⏱️ Test market data publisher stopped after {} seconds", duration_secs);
                break;
            }

            tick.tick().await;

            for symbol in &symbols {
                let base_price = match symbol.as_str() {
                    "AAPL" => 150.0,
                    "GOOGL" => 2800.0,
                    "MSFT" => 300.0,
                    "AMZN" => 3300.0,
                    _ => 100.0,
                };

                let price = base_price + (sequence as f64 * 0.01) % 10.0;
                let volume = 100.0 + (sequence as f64 * 10.0) % 1000.0;

                // Note: In production, this would publish to an event bus or message queue
                // For E2E tests, the Trading Service will generate synthetic market data
                // when stream_market_data is called with no real data provider

                // Log at DEBUG level to avoid flooding test output
                tracing::debug!(
                    symbol = %symbol,
                    price = price,
                    volume = volume,
                    sequence = sequence,
                    "Published test market data"
                );
            }

            sequence += 1;
        }
    })
}

/// Publish a single burst of market data events for testing
///
/// Useful for tests that need a specific number of market data events.
///
/// # Arguments
/// * `symbol` - Symbol to generate data for
/// * `count` - Number of events to generate
/// * `base_price` - Starting price
pub async fn publish_market_data_burst(
    symbol: &str,
    count: usize,
    base_price: f64,
) -> Result<()> {
    info!(
        "📊 Publishing {} test market data events for {}",
        count, symbol
    );

    for i in 0..count {
        let price = base_price + (i as f64 * 0.01);
        let volume = 100.0 + (i as f64);

        tracing::debug!(
            symbol = %symbol,
            price = price,
            volume = volume,
            sequence = i,
            "Published test market data burst event"
        );

        // In E2E tests, the Trading Service generates synthetic data
        // This function mainly serves to document the expected data format
    }

    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;

    #[tokio::test]
    async fn test_market_data_publisher_lifecycle() {
        let handle = start_test_market_data_publisher(
            vec!["TEST".to_string()],
            1, // Run for 1 second
        );

        // Wait for publisher to finish
        let _ = tokio::time::timeout(Duration::from_secs(2), handle).await;
    }

    #[tokio::test]
    async fn test_market_data_burst() {
        let result = publish_market_data_burst("TEST", 10, 100.0).await;
        assert!(result.is_ok());
    }
}
