//! # Financial Feature Engineering for HFT Transformers
//!
//! This module implements state-of-the-art feature extraction for financial
//! market microstructure data, optimized for transformer model input.
//!
//! ## Key Features
//!
//! - **Order Book Imbalance**: Bid/ask volume imbalances and pressure
//! - **Trade Flow Analysis**: Aggressive vs passive order flow patterns
//! - **Microstructure Signals**: Spread, volatility, intensity measures
//! - **Temporal Features**: Time-of-day, volume clocks, event sequences
//! - **Cross-Asset Signals**: Correlation and cointegration features
//!
//! ## Performance Optimizations
//!
//! - Pre-allocated feature vectors for zero-allocation extraction
//! - SIMD-optimized mathematical operations
//! - Incremental updates for streaming data
//! - <20μs feature extraction from raw market data

use common::types::{Price, Quantity, Symbol};
use std::collections::VecDeque;

use ml_core::native_types::{NativeDevice, NativeTensor};
use ml_core::cuda_autograd::GpuTensor;
use chrono::{DateTime, Datelike, Timelike, Utc};
use serde::{Deserialize, Serialize};

use super::*;


    #[test]
    fn test_feature_config_default() {
        let config = FeatureConfig::default();
        assert_eq!(config.lookback_window, 100);
        assert_eq!(config.book_levels, 5);
        assert!(config.use_order_book_features);
        assert!(config.use_trade_flow_features);
    }

    #[test]
    fn test_market_microstructure_from_tick() {
        let tick = MarketTick::new(
            Symbol::new("EURUSD")?,
            Price::from_f64(1.1000).unwrap(), // bid_price
            Price::from_f64(1.1002).unwrap(), // ask_price
            Price::from_f64(1.1001).unwrap(), // last_price
            Volume::new(1000.0),   // volume
            Quantity::from(500), // bid_size
            Quantity::from(300), // ask_size
            1234567890,          // timestamp_us
        );

        let micro = MarketMicrostructure::from_tick(&tick);
        assert_eq!(micro.bid_price, tick.bid_price);
        assert_eq!(micro.ask_price, tick.ask_price);
        assert!(micro.book_imbalance > 0.0); // More bid volume than ask
    }

    #[test]
    fn test_trade_flow_features() {
        let mut trades = Vec::new();

        // Create sample trades
        for i in 0..10 {
            let mut micro = MarketMicrostructure {
                timestamp: 1234567890 + i as u64 * 1000,
                bid_price: Price::from_f64(1.1000).unwrap(),
                ask_price: Price::from_f64(1.1002).unwrap(),
                bid_volume: Volume::new(100.0),
                ask_volume: Volume::new(100.0),
                mid_price: Price::from_f64(1.1001).unwrap(),
                spread: Price::from_f64(0.0002).unwrap(),
                last_price: Some(Price::from_f64(1.1001).unwrap()),
                last_volume: Some(Volume::new(100 + i as u64 * 10)),
                trade_direction: if i % 2 == 0 { 1 } else { -1 },
                book_imbalance: 0.0,
                vwap: None,
                trade_count: 1,
            };
            trades.push(micro);
        }

        let features = TradeFlowFeatures::extract(&trades, 1.0);
        let vector = features.to_vector();

        assert_eq!(vector.len(), 8);
        assert!(features.trade_intensity > 0.0);
        assert!(features.avg_trade_size > 0.0);
    }

    #[test]
    fn test_percentile_calculation() {
        let data = vec![1.0, 2.0, 3.0, 4.0, 5.0];
        assert_eq!(percentile(&data, 0.0), 1.0);
        assert_eq!(percentile(&data, 0.5), 3.0);
        assert_eq!(percentile(&data, 1.0), 5.0);

        let empty_data = vec![];
        assert_eq!(percentile(&empty_data, 0.5), 0.0);
    }

    #[tokio::test]
    async fn test_feature_extractor() {
        let config = FeatureConfig::default();
        let device = NativeDevice::Cuda(0);
        let mut extractor = FinancialFeatureExtractor::new(config, device);

        let tick = MarketTick::new(
            Symbol::new("EURUSD")?,
            Price::from_f64(1.1000).unwrap(), // bid_price
            Price::from_f64(1.1002).unwrap(), // ask_price
            Price::from_f64(1.1001).unwrap(), // last_price
            Volume::new(1000.0),   // volume
            Quantity::from(500), // bid_size
            Quantity::from(300), // ask_size
            1234567890,          // timestamp_us
        );

        let features_tensor = extractor.extract_features(&tick)?;
        let shape = features_tensor.shape();

        assert_eq!(shape.dims(), &[1, 32]); // Default output dimension
        assert!(extractor.average_extraction_time_us() > 0.0);
    }
}
