"""
Module Test Script
==================
Tests all modules to ensure they work correctly.
"""
# Run from project root: python tests/test_modules.py
import sys, os
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

import polars as pl
import numpy as np
from datetime import datetime, timedelta


def create_test_data(n: int = 500) -> pl.DataFrame:
    """Create synthetic OHLCV data for testing."""
    np.random.seed(42)
    
    base_price = 2000.0
    returns = np.random.randn(n) * 0.002
    prices = base_price * np.exp(np.cumsum(returns))
    
    return pl.DataFrame({
        "time": [datetime.now() - timedelta(minutes=15*i) for i in range(n-1, -1, -1)],
        "open": prices,
        "high": prices * (1 + np.abs(np.random.randn(n)) * 0.001),
        "low": prices * (1 - np.abs(np.random.randn(n)) * 0.001),
        "close": prices * (1 + np.random.randn(n) * 0.0005),
        "volume": np.random.randint(1000, 10000, n),
    })


def test_config():
    """Test configuration module."""
    print("\n" + "="*60)
    print("Testing: src/config.py")
    print("="*60)
    
    from src.config import TradingConfig, CapitalMode
    
    # Test small account
    config_small = TradingConfig(capital=5000)
    assert config_small.capital_mode == CapitalMode.SMALL
    assert config_small.risk.risk_per_trade == 1.5
    print(f"✓ Small account config: {config_small.capital_mode.value}")
    
    # Test medium account
    config_medium = TradingConfig(capital=50000)
    assert config_medium.capital_mode == CapitalMode.MEDIUM
    assert config_medium.risk.risk_per_trade == 0.5
    print(f"✓ Medium account config: {config_medium.capital_mode.value}")
    
    # Test position sizing
    lot = config_small.calculate_position_size(2000, 1995)
    assert lot > 0
    print(f"✓ Position sizing: {lot} lots")
    
    print("✓ Config module: PASSED")


def test_smc_polars():
    """Test SMC Polars module."""
    print("\n" + "="*60)
    print("Testing: src/smc_polars.py")
    print("="*60)
    
    from src.smc_polars import SMCAnalyzer, calculate_smc_summary
    
    df = create_test_data(500)
    analyzer = SMCAnalyzer(swing_length=5)
    
    # Test swing points
    df = analyzer.calculate_swing_points(df)
    assert "swing_high" in df.columns
    assert "swing_low" in df.columns
    print(f"✓ Swing points calculated")
    
    # Test FVG
    df = analyzer.calculate_fvg(df)
    assert "is_fvg_bull" in df.columns
    assert "is_fvg_bear" in df.columns
    print(f"✓ FVG calculated")
    
    # Test Order Blocks
    df = analyzer.calculate_order_blocks(df)
    assert "ob" in df.columns
    print(f"✓ Order Blocks calculated")
    
    # Test BOS/CHoCH
    df = analyzer.calculate_bos_choch(df)
    assert "bos" in df.columns
    assert "choch" in df.columns
    print(f"✓ BOS/CHoCH calculated")
    
    # Summary
    summary = calculate_smc_summary(df)
    print(f"  - Swing Highs: {summary['swing_highs']}")
    print(f"  - Swing Lows: {summary['swing_lows']}")
    print(f"  - Bullish FVG: {summary['bullish_fvg']}")
    print(f"  - Bearish FVG: {summary['bearish_fvg']}")
    
    print("✓ SMC Polars module: PASSED")


def test_feature_eng():
    """Test feature engineering module."""
    print("\n" + "="*60)
    print("Testing: src/feature_eng.py")
    print("="*60)
    
    from src.feature_eng import FeatureEngineer
    
    df = create_test_data(200)
    fe = FeatureEngineer()
    
    # Test RSI
    df = fe.calculate_rsi(df, period=14)
    assert "rsi" in df.columns
    rsi_range = df["rsi"].drop_nulls()
    assert rsi_range.min() >= 0 and rsi_range.max() <= 100
    print(f"✓ RSI calculated (range: {rsi_range.min():.1f} - {rsi_range.max():.1f})")
    
    # Test ATR
    df = fe.calculate_atr(df, period=14)
    assert "atr" in df.columns
    assert df["atr"].drop_nulls().min() >= 0
    print(f"✓ ATR calculated")
    
    # Test MACD
    df = fe.calculate_macd(df)
    assert "macd" in df.columns
    assert "macd_signal" in df.columns
    print(f"✓ MACD calculated")
    
    # Test Bollinger Bands
    df = fe.calculate_bollinger_bands(df)
    assert "bb_upper" in df.columns
    assert "bb_lower" in df.columns
    print(f"✓ Bollinger Bands calculated")
    
    # Test ML features
    df = fe.calculate_ml_features(df)
    assert "returns_1" in df.columns
    assert "volatility_20" in df.columns
    print(f"✓ ML features calculated")
    
    # Get feature columns
    feature_cols = fe.get_feature_columns(df)
    print(f"  - Total features: {len(feature_cols)}")
    
    print("✓ Feature Engineering module: PASSED")


def test_regime_detector():
    """Test regime detector module."""
    print("\n" + "="*60)
    print("Testing: src/regime_detector.py")
    print("="*60)
    
    from src.regime_detector import MarketRegimeDetector, FlashCrashDetector
    
    df = create_test_data(500)
    
    # Test HMM detector
    detector = MarketRegimeDetector(n_regimes=3)
    detector.fit(df.head(400))
    
    assert detector.fitted
    print(f"✓ HMM fitted")
    
    # Predict
    df_pred = detector.predict(df)
    assert "regime_name" in df_pred.columns
    print(f"✓ Regime prediction")
    
    # Get current state
    state = detector.get_current_state(df)
    print(f"  - Current regime: {state.regime.value}")
    print(f"  - Confidence: {state.confidence:.2%}")
    print(f"  - Recommendation: {state.recommendation}")
    
    # Test flash crash detector
    fc_detector = FlashCrashDetector(threshold_percent=1.0)
    is_flash, move = fc_detector.detect(df.tail(10))
    print(f"✓ Flash crash detector (flash={is_flash}, move={move:.2f}%)")
    
    print("✓ Regime Detector module: PASSED")


def test_risk_engine():
    """Test risk engine module."""
    print("\n" + "="*60)
    print("Testing: src/risk_engine.py")
    print("="*60)
    
    from src.config import TradingConfig
    from src.risk_engine import RiskEngine
    
    config = TradingConfig(capital=5000)
    engine = RiskEngine(config)
    
    # Test position sizing
    result = engine.calculate_position_size(
        entry_price=2000.0,
        stop_loss_price=1995.0,
        take_profit_price=2010.0,
        account_balance=5000.0,
        win_rate=0.55,
        avg_win_loss_ratio=2.0,
    )
    
    assert result.lot_size > 0
    print(f"✓ Position sizing: {result.lot_size} lots")
    print(f"  - Risk: ${result.risk_amount:.2f} ({result.risk_percent:.2f}%)")
    
    # Test order validation
    valid, reason = engine.validate_order(
        order_type="BUY",
        entry_price=2000.0,
        stop_loss=1995.0,
        take_profit=2010.0,
        lot_size=result.lot_size,
        current_price=2000.0,
        account_balance=5000.0,
    )
    
    assert valid
    print(f"✓ Order validation: {reason}")
    
    # Test risk check
    metrics = engine.check_risk(
        account_balance=5000.0,
        account_equity=4950.0,
        open_positions=pl.DataFrame({"ticket": [], "volume": [], "symbol": []}),
        current_price=2000.0,
    )
    
    print(f"✓ Risk check: can_trade={metrics.can_trade}")
    
    print("✓ Risk Engine module: PASSED")


def test_ml_model():
    """Test ML model module."""
    print("\n" + "="*60)
    print("Testing: src/ml_model.py")
    print("="*60)
    
    from src.ml_model import TradingModel
    
    # Create synthetic data with features
    np.random.seed(42)
    n = 500
    
    df = pl.DataFrame({
        "rsi": np.random.uniform(20, 80, n),
        "atr": np.random.uniform(0.5, 2.0, n),
        "macd": np.random.randn(n) * 0.001,
        "returns_1": np.random.randn(n) * 0.01,
    })
    
    # Create target
    target = ((df["rsi"].to_numpy() > 50).astype(int) * 0.5 +
              np.random.randint(0, 2, n) * 0.5)
    target = (target > 0.5).astype(int)
    df = df.with_columns([pl.Series("target", target)])
    
    # Test model
    model = TradingModel(confidence_threshold=0.6)
    feature_cols = ["rsi", "atr", "macd", "returns_1"]
    
    model.fit(df, feature_cols, "target")
    assert model.fitted
    print(f"✓ Model trained")
    
    # Test prediction
    prediction = model.predict(df, feature_cols)
    print(f"✓ Prediction: {prediction.signal} ({prediction.confidence:.2%})")
    
    # Test feature importance
    importance = model.get_feature_importance(3)
    print(f"✓ Feature importance: {list(importance.keys())}")
    
    print("✓ ML Model module: PASSED")


def test_utils():
    """Test utility module."""
    print("\n" + "="*60)
    print("Testing: src/utils.py")
    print("="*60)
    
    from src.utils import (
        validate_ohlcv_data,
        resample_ohlcv,
        calculate_trade_statistics,
        create_synthetic_data,
    )
    
    # Test synthetic data
    df = create_synthetic_data(100)
    assert len(df) == 100
    print(f"✓ Synthetic data created")
    
    # Test validation
    is_valid, issues = validate_ohlcv_data(df)
    assert is_valid
    print(f"✓ Data validation: valid={is_valid}")
    
    # Test resampling
    df_resampled = resample_ohlcv(df, "1h")
    assert len(df_resampled) < len(df)
    print(f"✓ Resampling: {len(df)} -> {len(df_resampled)} bars")
    
    # Test trade statistics
    trades = [
        {"pnl": 100, "is_win": True},
        {"pnl": -50, "is_win": False},
        {"pnl": 75, "is_win": True},
    ]
    stats = calculate_trade_statistics(trades)
    assert stats["total_trades"] == 3
    print(f"✓ Trade statistics: win_rate={stats['win_rate']:.2%}")
    
    print("✓ Utils module: PASSED")


def run_all_tests():
    """Run all module tests."""
    print("\n" + "="*60)
    print("SMART AUTOMATIC TRADING BOT + AI - MODULE TESTS")
    print("="*60)
    
    tests = [
        ("Config", test_config),
        ("SMC Polars", test_smc_polars),
        ("Feature Engineering", test_feature_eng),
        ("Regime Detector", test_regime_detector),
        ("Risk Engine", test_risk_engine),
        ("ML Model", test_ml_model),
        ("Utils", test_utils),
    ]
    
    results = []
    
    for name, test_func in tests:
        try:
            test_func()
            results.append((name, True, None))
        except Exception as e:
            results.append((name, False, str(e)))
            print(f"✗ {name} module: FAILED - {e}")
    
    # Summary
    print("\n" + "="*60)
    print("TEST SUMMARY")
    print("="*60)
    
    passed = sum(1 for _, success, _ in results if success)
    total = len(results)
    
    for name, success, error in results:
        status = "✓ PASSED" if success else f"✗ FAILED: {error}"
        print(f"  {name}: {status}")
    
    print("-"*60)
    print(f"Total: {passed}/{total} tests passed")
    print("="*60)
    
    return passed == total


if __name__ == "__main__":
    success = run_all_tests()
    sys.exit(0 if success else 1)
