//! Common test utilities for Foxhunt HFT System
//!
//! This module provides shared testing infrastructure to eliminate duplication
//! across the 80+ test files in the project.
//!
//! # Usage
//! ```rust
//! use common::*;
use common::test_config::*;
use common::mock_data::*;
//! ```

pub mod database_helper;

// Test Configuration Module
pub mod test_config {
    
    /// Unified test configuration for all test types
    #[derive(Debug, Clone)]
    pub struct UnifiedTestConfig {
        pub environment_name: String,
        pub docker_compose_file: Option<String>,
        pub cleanup_on_exit: bool,
        pub persist_data: bool,
        pub log_level: String,
        pub test_database_url: String,
        pub test_redis_url: String,
        pub test_influxdb_url: String,
        pub parallel_tests: bool,
        pub timeout_seconds: u64,
        pub max_retries: u32,
    }
    
    impl Default for UnifiedTestConfig {
        fn default() -> Self {
            Self {
                environment_name: "test".to_string(),
                docker_compose_file: Some("docker-compose.test.yml".to_string()),
                cleanup_on_exit: true,
                persist_data: false,
                log_level: "debug".to_string(),
                test_database_url: std::env::var("TEST_DATABASE_URL")
                    .unwrap_or_else(|_| "postgresql://localhost:5432/hft_testing".to_string()),
                test_redis_url: std::env::var("TEST_REDIS_URL")
                    .unwrap_or_else(|_| "redis://localhost:6379/0".to_string()),
                test_influxdb_url: std::env::var("TEST_INFLUXDB_URL")
                    .unwrap_or_else(|_| "http://localhost:8086".to_string()),
                parallel_tests: true,
                timeout_seconds: 30,
                max_retries: 3,
            }
        }
    }
}

// Mock Data Generation Module
pub mod mock_data {
    // Note: These imports are commented out as they require the common crate
    // Tests using these should import from the actual crates directly
    // use ::common::error::CommonError;
    // use ::common::error::CommonResult;
    // use ::common::database::DatabaseConfig;
    // use ::common::database::DatabasePool;
    // use ::common::Order;
    // use ::common::Position;
    // use ::common::Symbol;
    // use ::common::Price;
    // use ::common::Quantity;
    // use ::common::HftTimestamp;

    /// Generate mock order using canonical types
    ///
    /// Note: This is a placeholder - actual tests should create orders using the proper types
    pub fn create_mock_order_data() -> MockOrderData {
        MockOrderData {
            symbol: "BTCUSD".to_string(),
            side: "Buy".to_string(),
            quantity: 1.0,
            price: 50000.0,
        }
    }

    /// Mock order data for tests
    #[derive(Debug, Clone)]
    pub struct MockOrderData {
        pub symbol: String,
        pub side: String,
        pub quantity: f64,
        pub price: f64,
    }

    /// Generate mock market data
    pub fn create_mock_market_tick(symbol: &str) -> MockMarketTick {
        MockMarketTick {
            symbol: symbol.to_string(),
            price: 50000.0,
            volume: 100.0,
            timestamp: chrono::Utc::now().timestamp_millis(),
        }
    }
    
    /// Mock market tick for tests
    #[derive(Debug, Clone)]
    pub struct MockMarketTick {
        pub symbol: String,
        pub price: f64,
        pub volume: f64,
        pub timestamp: i64,
    }
}

// Test Utilities Module  
pub mod test_utils {
    use std::time::Duration;
    use tokio::time::timeout;
    
    /// Async test helper with timeout
    pub async fn run_with_timeout<F, T>(future: F, timeout_secs: u64) -> Result<T, &'static str>
    where
        F: std::future::Future<Output = T>,
    {
        timeout(Duration::from_secs(timeout_secs), future)
            .await
            .map_err(|_| "Test timed out")
    }
    
    /// Setup tracing for tests
    pub fn setup_test_tracing() {
        use tracing_subscriber::EnvFilter;
        
        let _ = tracing_subscriber::fmt()
            .with_test_writer()
            .with_env_filter(EnvFilter::from_default_env())
            .try_init();
    }
    
    /// Generate test symbol name
    pub fn test_symbol(name: &str) -> String {
        name.to_string()
    }

    /// Generate test price value
    pub fn test_price(value: f64) -> f64 {
        value
    }

    /// Generate test quantity value
    pub fn test_quantity(value: f64) -> f64 {
        value
    }
    
    /// Common test assertions
    pub mod assertions {
        use std::time::Duration;
        
        /// Assert that a value is within a percentage tolerance
        pub fn assert_within_percent(actual: f64, expected: f64, percent: f64) {
            let tolerance = expected * (percent / 100.0);
            let diff = (actual - expected).abs();
            assert!(
                diff <= tolerance,
                "Value {} is not within {}% of expected {}, difference: {}",
                actual, percent, expected, diff
            );
        }
        
        /// Assert that latency is within `HFT` requirements
        pub fn assert_hft_latency(duration: Duration, max_microseconds: u64) {
            let micros = duration.as_micros() as u64;
            assert!(
                micros <= max_microseconds,
                "Latency {}μs exceeds HFT requirement of {}μs",
                micros, max_microseconds
            );
        }
    }
}

// Async Test Patterns Module
pub mod async_patterns {
    use tokio::sync::broadcast;
    
    /// Proper broadcast receiver pattern for tests
    pub struct TestBroadcastReceiver<T> {
        receiver: broadcast::Receiver<T>,
    }
    
    impl<T> TestBroadcastReceiver<T> 
    where
        T: Clone + Send + 'static,
    {
        pub fn new(receiver: broadcast::Receiver<T>) -> Self {
            Self { receiver }
        }
        
        pub async fn wait_for_shutdown(mut self) -> Result<(), broadcast::error::RecvError> {
            loop {
                tokio::select! {
                    msg = self.receiver.recv() => {
                        match msg {
                            Ok(_) => return Ok(()),
                            Err(e) => return Err(e),
                        }
                    }
                }
            }
        }
    }
}

// REMOVED: All pub use statements eliminated per cleanup requirements
// Tests must import from canonical sources:
// - tests::test_common::database_helper::*
// - tests::test_common::test_config::UnifiedTestConfig
// - tests::test_common::mock_data::*
// - tests::test_common::test_utils::*
// - tests::test_common::async_patterns::TestBroadcastReceiver

// Re-export canonical types for test convenience
