//! Validation Test: Real-World DBN File Filtering
//!
//! This test validates that the DBN loader correctly filters files in the
//! actual test_data directory, demonstrating production-ready behavior.

use backtesting_service::dbn_data_source::DbnDataSource;
use std::collections::HashMap;

#[tokio::test]
async fn test_real_directory_filters_correctly() {
    // Find workspace root
    let current_dir = std::env::current_dir().expect("INVARIANT: Current directory should be accessible");
    let workspace_root = current_dir
        .ancestors()
        .find(|p| p.join("test_data").exists())
        .expect("Could not find workspace root");

    let test_data_dir = workspace_root.join("test_data/real/databento");

    if !test_data_dir.exists() {
        eprintln!("Test data directory not found, skipping test");
        return;
    }

    // Create data source from directory scan
    let data_source = DbnDataSource::from_directory(test_data_dir.to_str().expect("INVARIANT: Path should be valid UTF-8"))
        .await
        .expect("Failed to scan directory");

    let symbols = data_source.available_symbols();
    println!("Found {} symbols in test_data", symbols.len());

    // Validate that we found valid symbols
    assert!(!symbols.is_empty(), "Should find at least one symbol");

    // Check specific files exist
    for symbol in &symbols {
        let file_paths = data_source.get_file_paths(symbol).unwrap();
        println!("Symbol {}: {} files", symbol, file_paths.len());

        // All files should end with .dbn (not .tmp, .uncompressed.dbn, etc.)
        for file_path in &file_paths {
            assert!(
                file_path.ends_with(".dbn"),
                "File should end with .dbn: {}",
                file_path
            );
            assert!(
                !file_path.ends_with(".tmp"),
                "Should not include .tmp files: {}",
                file_path
            );
            assert!(
                !file_path.ends_with(".uncompressed.dbn"),
                "Should not include .uncompressed.dbn: {}",
                file_path
            );
            assert!(
                !file_path.ends_with(".dbn.zst"),
                "Should not include compressed files: {}",
                file_path
            );
        }
    }

    println!("✅ All files validated successfully");
}

#[tokio::test]
async fn test_load_bars_with_filtered_directory() {
    // Find workspace root
    let current_dir = std::env::current_dir().expect("INVARIANT: Current directory should be accessible");
    let workspace_root = current_dir
        .ancestors()
        .find(|p| p.join("test_data").exists())
        .expect("Could not find workspace root");

    let test_data_dir = workspace_root.join("test_data/real/databento");

    if !test_data_dir.exists() {
        eprintln!("Test data directory not found, skipping test");
        return;
    }

    // Create data source from directory
    let data_source = DbnDataSource::from_directory(test_data_dir.to_str().expect("INVARIANT: Path should be valid UTF-8"))
        .await
        .expect("Failed to scan directory");

    let symbols = data_source.available_symbols();

    // Try to load bars for the first symbol
    if let Some(symbol) = symbols.first() {
        let bars = data_source
            .load_ohlcv_bars(symbol)
            .await
            .expect("Failed to load bars");

        println!("Loaded {} bars for symbol {}", bars.len(), symbol);
        assert!(!bars.is_empty(), "Should load at least one bar");

        // Validate bar data
        if let Some(first_bar) = bars.first() {
            println!(
                "First bar: timestamp={}, close={}",
                first_bar.timestamp, first_bar.close
            );
            assert_eq!(first_bar.symbol, *symbol);
        }
    }
}

#[tokio::test]
async fn test_manual_symbol_validation() {
    // Test with manually configured symbols
    let current_dir = std::env::current_dir().expect("INVARIANT: Current directory should be accessible");
    let workspace_root = current_dir
        .ancestors()
        .find(|p| p.join("test_data").exists())
        .expect("Could not find workspace root");

    let test_data_dir = workspace_root.join("test_data/real/databento");

    // Check which files exist
    let es_fut_file = test_data_dir.join("ES.FUT_ohlcv-1m_2024-01-02.dbn");
    let nq_fut_file = test_data_dir.join("NQ.FUT_ohlcv-1m_2024-01-02.dbn");

    let mut file_mapping = HashMap::new();

    if es_fut_file.exists() {
        file_mapping.insert(
            "ES.FUT".to_string(),
            es_fut_file.to_string_lossy().to_string(),
        );
    }

    if nq_fut_file.exists() {
        file_mapping.insert(
            "NQ.FUT".to_string(),
            nq_fut_file.to_string_lossy().to_string(),
        );
    }

    if file_mapping.is_empty() {
        eprintln!("No test files found, skipping test");
        return;
    }

    let data_source = DbnDataSource::new(file_mapping)
        .await
        .expect("Failed to create data source");

    // Load bars for each symbol
    for symbol in data_source.available_symbols() {
        let bars = data_source
            .load_ohlcv_bars(&symbol)
            .await
            .expect("Failed to load bars");

        println!("Symbol {}: {} bars", symbol, bars.len());
        assert!(!bars.is_empty());
    }
}

#[test]
fn test_extension_filtering_unit_tests() {
    use backtesting_service::dbn_data_source::is_valid_dbn_file;

    // Valid files
    assert!(is_valid_dbn_file("ES.FUT.dbn"));
    assert!(is_valid_dbn_file("/path/to/data.dbn"));
    assert!(is_valid_dbn_file("test.DBN"));

    // Invalid files
    assert!(!is_valid_dbn_file("file.dbn.zst"));
    assert!(!is_valid_dbn_file("file.dbn.gz"));
    assert!(!is_valid_dbn_file("file.dbn.bz2"));
    assert!(!is_valid_dbn_file("file.dbn.tmp"));
    assert!(!is_valid_dbn_file("file.dbn.old"));
    assert!(!is_valid_dbn_file("file.txt"));
    assert!(!is_valid_dbn_file("file"));

    // Case insensitive
    assert!(!is_valid_dbn_file("file.dbn.ZST"));
    assert!(!is_valid_dbn_file("file.dbn.Gz"));
    assert!(!is_valid_dbn_file("file.dbn.TMP"));
}
