//! Binance ETHUSDT Real Data Integration Tests
//!
//! Validates open deviation bar construction using real ETHUSDT market data from CSV.
//! Tests multiple threshold scenarios and validates data integrity.

use opendeviationbar::{FixedPoint, OpenDeviationBar, OpenDeviationBarProcessor};
use opendeviationbar_core::test_data_loader::load_ethusdt_test_data;

#[test]
fn test_ethusdt_data_integrity() {
    // Validate real ETHUSDT CSV data integrity
    let trades = load_ethusdt_test_data().expect("Failed to load ETHUSDT test data");

    assert_eq!(trades.len(), 10000, "Expected 10,000 ETHUSDT trades");

    // Validate temporal ordering
    for i in 1..trades.len() {
        assert!(
            trades[i].timestamp >= trades[i - 1].timestamp,
            "Temporal ordering violation at trade {}: {} < {}",
            i,
            trades[i].timestamp,
            trades[i - 1].timestamp
        );
    }

    // Validate price and volume are positive
    for (i, trade) in trades.iter().enumerate() {
        assert!(
            trade.price > FixedPoint(0),
            "Trade {}: Invalid price {}",
            i,
            trade.price
        );
        assert!(
            trade.volume > FixedPoint(0),
            "Trade {}: Invalid volume {}",
            i,
            trade.volume
        );
    }

    println!(
        "✅ ETHUSDT data integrity validated: {} trades",
        trades.len()
    );
}

#[test]
fn test_ethusdt_standard_threshold() {
    // Test standard 25 dbps (0.025%) threshold for real market data
    let mut processor = OpenDeviationBarProcessor::new(25)
        .expect("Failed to create processor with valid threshold");
    let trades = load_ethusdt_test_data().expect("Failed to load ETHUSDT test data");

    let open_deviation_bars = processor
        .process_agg_trade_records(&trades)
        .expect("Failed to process ETHUSDT trades");

    assert!(
        !open_deviation_bars.is_empty(),
        "Should produce at least one open deviation bar"
    );

    println!(
        "ETHUSDT (25 dbps): {} trades → {} open deviation bars",
        trades.len(),
        open_deviation_bars.len()
    );

    validate_ohlcv_integrity(&open_deviation_bars);
    validate_temporal_ordering(&open_deviation_bars);
}

#[test]
fn test_ethusdt_medium_threshold() {
    // Test medium 50 dbps (0.05%) threshold
    let mut processor = OpenDeviationBarProcessor::new(50)
        .expect("Failed to create processor with valid threshold");
    let trades = load_ethusdt_test_data().expect("Failed to load ETHUSDT test data");

    let open_deviation_bars = processor
        .process_agg_trade_records(&trades)
        .expect("Failed to process ETHUSDT trades");

    assert!(
        !open_deviation_bars.is_empty(),
        "Should produce at least one open deviation bar"
    );

    println!(
        "ETHUSDT (50 dbps): {} trades → {} open deviation bars",
        trades.len(),
        open_deviation_bars.len()
    );

    validate_ohlcv_integrity(&open_deviation_bars);
    validate_temporal_ordering(&open_deviation_bars);
}

#[test]
fn test_ethusdt_wide_threshold() {
    // Test wide 100 dbps (0.1%) threshold
    let mut processor = OpenDeviationBarProcessor::new(100)
        .expect("Failed to create processor with valid threshold");
    let trades = load_ethusdt_test_data().expect("Failed to load ETHUSDT test data");

    let open_deviation_bars = processor
        .process_agg_trade_records(&trades)
        .expect("Failed to process ETHUSDT trades");

    assert!(
        !open_deviation_bars.is_empty(),
        "Should produce at least one open deviation bar"
    );

    println!(
        "ETHUSDT (100 dbps): {} trades → {} open deviation bars",
        trades.len(),
        open_deviation_bars.len()
    );

    validate_ohlcv_integrity(&open_deviation_bars);
    validate_temporal_ordering(&open_deviation_bars);
}

#[test]
fn test_ethusdt_threshold_scaling() {
    // Verify that bar count decreases with wider thresholds
    let trades = load_ethusdt_test_data().expect("Failed to load ETHUSDT test data");

    let bars_25 = OpenDeviationBarProcessor::new(25)
        .expect("Failed to create processor")
        .process_agg_trade_records(&trades)
        .expect("Failed to process trades");

    let bars_50 = OpenDeviationBarProcessor::new(50)
        .expect("Failed to create processor")
        .process_agg_trade_records(&trades)
        .expect("Failed to process trades");

    let bars_100 = OpenDeviationBarProcessor::new(100)
        .expect("Failed to create processor")
        .process_agg_trade_records(&trades)
        .expect("Failed to process trades");

    assert!(
        bars_25.len() >= bars_50.len(),
        "25 dbps should produce >= bars than 50 dbps (got {} vs {})",
        bars_25.len(),
        bars_50.len()
    );

    assert!(
        bars_50.len() >= bars_100.len(),
        "50 dbps should produce >= bars than 100 dbps (got {} vs {})",
        bars_50.len(),
        bars_100.len()
    );

    println!("ETHUSDT threshold scaling:");
    println!("  25 dbps: {} bars", bars_25.len());
    println!("  50 dbps: {} bars", bars_50.len());
    println!(" 100 dbps: {} bars", bars_100.len());
}

/// Validates OHLCV integrity for all open deviation bars
fn validate_ohlcv_integrity(open_deviation_bars: &[OpenDeviationBar]) {
    for (i, bar) in open_deviation_bars.iter().enumerate() {
        assert!(
            bar.high >= bar.open,
            "Bar {}: High ({}) should be >= open ({})",
            i,
            bar.high,
            bar.open
        );
        assert!(
            bar.high >= bar.close,
            "Bar {}: High ({}) should be >= close ({})",
            i,
            bar.high,
            bar.close
        );
        assert!(
            bar.low <= bar.open,
            "Bar {}: Low ({}) should be <= open ({})",
            i,
            bar.low,
            bar.open
        );
        assert!(
            bar.low <= bar.close,
            "Bar {}: Low ({}) should be <= close ({})",
            i,
            bar.low,
            bar.close
        );
        assert!(
            bar.volume > 0, // Issue #88: i128 volume
            "Bar {}: Volume should be positive",
            i
        );
    }
}

/// Validates temporal ordering of open deviation bars
fn validate_temporal_ordering(open_deviation_bars: &[OpenDeviationBar]) {
    for (i, bar) in open_deviation_bars.iter().enumerate() {
        assert!(
            bar.open_time <= bar.close_time,
            "Bar {}: Open time ({}) should be <= close time ({})",
            i,
            bar.open_time,
            bar.close_time
        );

        if i > 0 {
            assert!(
                open_deviation_bars[i - 1].close_time <= bar.open_time,
                "Bar {}: Previous close time ({}) should be <= current open time ({})",
                i,
                open_deviation_bars[i - 1].close_time,
                bar.open_time
            );
        }
    }
}
