//! Smoke Tests - End-to-End System Validation
//!
//! Automated smoke tests to validate complete system functionality after deployment.
//! Tests are organized by category and can run selectively based on service availability.
//!
//! ## Test Categories
//! - Infrastructure Health (PostgreSQL, Redis, Vault, InfluxDB)
//! - Service Health (API Gateway, Trading, Backtesting, ML Training)
//! - Authentication Flow (JWT, MFA, Session Management)
//! - Basic Order Flow (Submit, Query, Cancel, Positions)
//! - Market Data (Streaming, Historical Queries)
//! - ML Inference (Predictions, Feature Engineering)
//! - Compliance (Audit Logs, Best Execution, Risk Checks)
//! - Metrics and Monitoring (Prometheus, Grafana)
//!
//! ## Usage
//! ```bash
//! # Run all smoke tests
//! cargo test --test smoke_tests
//!
//! # Run specific category
//! cargo test --test smoke_tests infrastructure_health
//! cargo test --test smoke_tests service_health
//! cargo test --test smoke_tests basic_order_flow
//!
//! # Run with logging
//! RUST_LOG=debug cargo test --test smoke_tests -- --nocapture
//! ```

pub mod infrastructure_health;
pub mod service_health;
pub mod authentication_flow;
pub mod basic_order_flow;

/// Common test utilities and helpers
pub mod common {
    use std::time::Duration;
    use tokio::time::timeout;

    /// Standard timeout for smoke tests (10 seconds)
    pub const SMOKE_TEST_TIMEOUT: Duration = Duration::from_secs(10);

    /// Standard timeout for infrastructure checks (5 seconds)
    pub const INFRA_TEST_TIMEOUT: Duration = Duration::from_secs(5);

    /// Load database URL from environment
    pub fn database_url() -> String {
        std::env::var("DATABASE_URL")
            .unwrap_or_else(|_| "postgresql://foxhunt:foxhunt_dev_password@localhost:5432/foxhunt".to_string())
    }

    /// Load Redis URL from environment
    pub fn redis_url() -> String {
        std::env::var("REDIS_URL")
            .unwrap_or_else(|_| "redis://localhost:6379".to_string())
    }

    /// Load Vault URL from environment
    pub fn vault_url() -> String {
        std::env::var("VAULT_ADDR")
            .unwrap_or_else(|_| "http://localhost:8200".to_string())
    }

    /// Load InfluxDB URL from environment
    pub fn influxdb_url() -> String {
        std::env::var("INFLUXDB_URL")
            .unwrap_or_else(|_| "http://localhost:8086".to_string())
    }

    /// Load API Gateway URL from environment
    pub fn api_url() -> String {
        std::env::var("API_GATEWAY_URL")
            .unwrap_or_else(|_| "http://localhost:50051".to_string())
    }

    /// Load Trading Service URL from environment
    pub fn trading_service_url() -> String {
        std::env::var("TRADING_SERVICE_URL")
            .unwrap_or_else(|_| "http://localhost:50052".to_string())
    }

    /// Load Backtesting Service URL from environment
    pub fn backtesting_service_url() -> String {
        std::env::var("BACKTESTING_SERVICE_URL")
            .unwrap_or_else(|_| "http://localhost:50053".to_string())
    }

    /// Load ML Training Service URL from environment
    pub fn ml_training_service_url() -> String {
        std::env::var("ML_TRAINING_SERVICE_URL")
            .unwrap_or_else(|_| "http://localhost:50054".to_string())
    }

    /// Load Prometheus URL from environment
    pub fn prometheus_url() -> String {
        std::env::var("PROMETHEUS_URL")
            .unwrap_or_else(|_| "http://localhost:9090".to_string())
    }

    /// Load Grafana URL from environment
    pub fn grafana_url() -> String {
        std::env::var("GRAFANA_URL")
            .unwrap_or_else(|_| "http://localhost:3000".to_string())
    }

    /// Run a test with timeout
    pub async fn with_timeout<F, T>(future: F) -> Result<T, Box<dyn std::error::Error>>
    where
        F: std::future::Future<Output = Result<T, Box<dyn std::error::Error>>>,
    {
        match timeout(SMOKE_TEST_TIMEOUT, future).await {
            Ok(result) => result,
            Err(_) => Err("Test timed out after 10 seconds".into()),
        }
    }

    /// Skip test if service is not available
    ///
    /// This allows tests to be skipped gracefully when services are down
    #[macro_export]
    macro_rules! skip_if_unavailable {
        ($service:expr, $test:block) => {
            match $test {
                Ok(result) => result,
                Err(e) if e.to_string().contains("connection refused") ||
                          e.to_string().contains("connection reset") ||
                          e.to_string().contains("timed out") => {
                    eprintln!("⏭️  Skipping test - {} not available: {}", $service, e);
                    return;
                }
                Err(e) => panic!("Test failed: {}", e),
            }
        };
    }
}
