"""
Tests for Data Models
"""

import pytest
from pydantic import ValidationError
from api.models import (
    TradingConfig, OptimizationRequest, SettingsUpdate,
    ForceCloseRequest, WatchlistRequest
)


class TestTradingConfig:
    """Tests pour TradingConfig"""

    def test_valid_config(self):
        """Config valide"""
        config = TradingConfig(
            STOP_LOSS_PERCENT=5.0,
            TAKE_PROFIT_PERCENT=10.0,
            MAX_ORDER_SIZE=100,
            RSI_PERIOD=14,
            RSI_OVERSOLD=30.0,
            RSI_OVERBOUGHT=70.0,
            EMA_SHORT=12,
            EMA_LONG=26,
            BB_PERIOD=20,
            BB_STD=2.0,
            REQUIRED_SIGNALS=2
        )
        assert config.STOP_LOSS_PERCENT == 5.0
        assert config.EMA_LONG > config.EMA_SHORT

    def test_invalid_stop_loss(self):
        """Stop loss invalide"""
        with pytest.raises(ValidationError):
            TradingConfig(
                STOP_LOSS_PERCENT=-1.0,  # Négatif invalide
                TAKE_PROFIT_PERCENT=10.0,
                MAX_ORDER_SIZE=100,
                RSI_PERIOD=14,
                RSI_OVERSOLD=30.0,
                RSI_OVERBOUGHT=70.0,
                EMA_SHORT=12,
                EMA_LONG=26,
                BB_PERIOD=20,
                BB_STD=2.0,
                REQUIRED_SIGNALS=2
            )

    def test_ema_validation(self):
        """EMA_LONG doit être > EMA_SHORT"""
        with pytest.raises(ValidationError, match="EMA_LONG doit être > EMA_SHORT"):
            TradingConfig(
                STOP_LOSS_PERCENT=5.0,
                TAKE_PROFIT_PERCENT=10.0,
                MAX_ORDER_SIZE=100,
                RSI_PERIOD=14,
                RSI_OVERSOLD=30.0,
                RSI_OVERBOUGHT=70.0,
                EMA_SHORT=26,
                EMA_LONG=12,  # Invalide: plus petit que SHORT
                BB_PERIOD=20,
                BB_STD=2.0,
                REQUIRED_SIGNALS=2
            )


class TestOptimizationRequest:
    """Tests pour OptimizationRequest"""

    def test_valid_request(self):
        """Requête valide"""
        req = OptimizationRequest(
            mode='quick',
            symbols=['BTCUSDT', 'ETHUSDT']
        )
        assert req.mode == 'quick'
        assert len(req.symbols) == 2

    def test_invalid_symbol(self):
        """Symbole invalide (ne termine pas par USDT)"""
        with pytest.raises(ValidationError, match="must end with USDT"):
            OptimizationRequest(
                mode='quick',
                symbols=['BTCEUR']  # Invalide
            )

    def test_too_many_symbols(self):
        """Trop de symboles"""
        with pytest.raises(ValidationError):
            OptimizationRequest(
                mode='quick',
                symbols=['BTCUSDT'] * 101  # Max 100
            )


class TestWatchlistRequest:
    """Tests pour WatchlistRequest"""

    def test_deduplication(self):
        """Dédupliquer les symboles"""
        req = WatchlistRequest(
            symbols=['BTCUSDT', 'ETHUSDT', 'BTCUSDT']  # Doublon
        )
        assert len(req.symbols) == 2  # Dédupliqué
        assert 'BTCUSDT' in req.symbols
        assert 'ETHUSDT' in req.symbols


class TestSettingsUpdate:
    """Tests pour SettingsUpdate"""

    def test_partial_update(self):
        """Mise à jour partielle"""
        settings = SettingsUpdate(auto_trade=True)
        assert settings.auto_trade is True
        assert settings.max_positions is None  # Non fourni

    def test_invalid_values(self):
        """Valeurs invalides"""
        with pytest.raises(ValidationError):
            SettingsUpdate(max_positions=0)  # Min 1

        with pytest.raises(ValidationError):
            SettingsUpdate(risk_per_trade=20.0)  # Max 10
