"""Tests for strategy grouping module."""

import pytest
from src.autopilot.strategy_groups import (
    StrategyGroup,
    STRATEGY_TO_GROUP,
    GROUP_TO_STRATEGIES,
    get_strategy_group,
    get_strategies_in_group,
    get_all_groups,
    get_best_strategy_in_group,
    convert_strategy_to_group_label,
)


class TestStrategyGroupMappings:
    """Tests for strategy group mappings."""

    def test_all_strategies_have_group(self):
        """Verify all registered strategies are mapped to a group."""
        # These are the strategies registered in src/strategies/__init__.py
        expected_strategies = [
            "rsi", "macd", "moving_average", "confirmed", "divergence",
            "bollinger_mean_reversion", "dca", "grid", "momentum",
            "consensus", "pairs_trading", "volatility_breakout",
            "sentiment", "market_making"
        ]
        
        for strategy in expected_strategies:
            group = get_strategy_group(strategy)
            assert group is not None, f"Strategy '{strategy}' is not mapped to any group"

    def test_get_strategy_group_case_insensitive(self):
        """Test that strategy lookup is case-insensitive."""
        assert get_strategy_group("RSI") == get_strategy_group("rsi")
        assert get_strategy_group("MACD") == get_strategy_group("macd")
        assert get_strategy_group("Moving_Average") == get_strategy_group("moving_average")

    def test_get_strategy_group_unknown(self):
        """Test that unknown strategies return None."""
        assert get_strategy_group("nonexistent_strategy") is None
        assert get_strategy_group("") is None

    def test_group_to_strategies_reverse_mapping(self):
        """Verify GROUP_TO_STRATEGIES is the reverse of STRATEGY_TO_GROUP."""
        for strategy, group in STRATEGY_TO_GROUP.items():
            assert strategy in GROUP_TO_STRATEGIES[group]

    def test_all_groups_have_strategies(self):
        """Verify all groups have at least one strategy."""
        for group in StrategyGroup:
            strategies = get_strategies_in_group(group)
            assert len(strategies) > 0, f"Group '{group}' has no strategies"


class TestGetAllGroups:
    """Tests for get_all_groups function."""

    def test_returns_all_groups(self):
        """Verify all groups are returned."""
        groups = get_all_groups()
        assert len(groups) == 5
        assert StrategyGroup.TREND_FOLLOWING in groups
        assert StrategyGroup.MEAN_REVERSION in groups
        assert StrategyGroup.MOMENTUM in groups
        assert StrategyGroup.MARKET_MAKING in groups
        assert StrategyGroup.SENTIMENT_BASED in groups


class TestGetStrategiesInGroup:
    """Tests for get_strategies_in_group function."""

    def test_trend_following_strategies(self):
        """Test trend following group contains expected strategies."""
        strategies = get_strategies_in_group(StrategyGroup.TREND_FOLLOWING)
        assert "moving_average" in strategies
        assert "macd" in strategies
        assert "confirmed" in strategies

    def test_mean_reversion_strategies(self):
        """Test mean reversion group contains expected strategies."""
        strategies = get_strategies_in_group(StrategyGroup.MEAN_REVERSION)
        assert "rsi" in strategies
        assert "bollinger_mean_reversion" in strategies
        assert "grid" in strategies

    def test_momentum_strategies(self):
        """Test momentum group contains expected strategies."""
        strategies = get_strategies_in_group(StrategyGroup.MOMENTUM)
        assert "momentum" in strategies
        assert "volatility_breakout" in strategies


class TestGetBestStrategyInGroup:
    """Tests for get_best_strategy_in_group function."""

    def test_trend_following_high_adx(self):
        """Test trend following selection with high ADX."""
        features = {"adx": 35.0, "rsi": 50.0, "atr_percent": 2.0, "volume_ratio": 1.0}
        strategy, confidence = get_best_strategy_in_group(
            StrategyGroup.TREND_FOLLOWING, features
        )
        assert strategy == "confirmed"
        assert confidence > 0.5

    def test_mean_reversion_extreme_rsi(self):
        """Test mean reversion selection with extreme RSI."""
        features = {"adx": 15.0, "rsi": 25.0, "atr_percent": 1.5, "volume_ratio": 1.0}
        strategy, confidence = get_best_strategy_in_group(
            StrategyGroup.MEAN_REVERSION, features
        )
        assert strategy == "rsi"
        assert confidence > 0.5

    def test_momentum_high_volume(self):
        """Test momentum selection with high volume."""
        features = {"adx": 25.0, "rsi": 55.0, "atr_percent": 3.0, "volume_ratio": 2.0}
        strategy, confidence = get_best_strategy_in_group(
            StrategyGroup.MOMENTUM, features
        )
        assert strategy == "volatility_breakout"
        assert confidence > 0.5

    def test_respects_available_strategies(self):
        """Test that only available strategies are selected."""
        features = {"adx": 35.0, "rsi": 50.0}
        # Only MACD available from trend following
        strategy, confidence = get_best_strategy_in_group(
            StrategyGroup.TREND_FOLLOWING,
            features,
            available_strategies=["macd"]
        )
        assert strategy == "macd"

    def test_fallback_when_no_strategies_available(self):
        """Test fallback when no strategies in group are available."""
        features = {"adx": 25.0, "rsi": 50.0}
        strategy, confidence = get_best_strategy_in_group(
            StrategyGroup.TREND_FOLLOWING,
            features,
            available_strategies=["some_other_strategy"]
        )
        # Should return safe default
        assert strategy == "rsi"
        assert confidence == 0.5


class TestConvertStrategyToGroupLabel:
    """Tests for convert_strategy_to_group_label function."""

    def test_converts_known_strategies(self):
        """Test conversion of known strategies."""
        assert convert_strategy_to_group_label("rsi") == "mean_reversion"
        assert convert_strategy_to_group_label("macd") == "trend_following"
        assert convert_strategy_to_group_label("momentum") == "momentum"
        assert convert_strategy_to_group_label("dca") == "market_making"
        assert convert_strategy_to_group_label("sentiment") == "sentiment_based"

    def test_unknown_strategy_returns_original(self):
        """Test that unknown strategies return original name."""
        assert convert_strategy_to_group_label("unknown") == "unknown"
