"""
Unit tests for league configuration system.

Tests:
- Config loading and registry
- Config immutability
- Abstract method implementations
- League-specific settings
"""
import pytest
from pydantic import ValidationError

from app.config import (
    BaseGameConfig,
    SbaConfig,
    PdConfig,
    LEAGUE_CONFIGS,
    get_league_config
)


class TestBaseGameConfig:
    """Tests for BaseGameConfig abstract class."""

    def test_cannot_instantiate_abstract_base(self):
        """BaseGameConfig cannot be instantiated directly."""
        with pytest.raises(TypeError):
            BaseGameConfig(league_id="test")


class TestSbaConfig:
    """Tests for SBA league configuration."""

    def test_sba_config_creation(self):
        """Can create SBA config instance."""
        config = SbaConfig()
        assert config.league_id == "sba"
        assert config.version == "1.0.0"

    def test_sba_basic_rules(self):
        """SBA uses standard baseball rules."""
        config = SbaConfig()
        assert config.innings == 9
        assert config.outs_per_inning == 3

    def test_sba_result_chart_name(self):
        """SBA uses sba_standard_v1 chart."""
        config = SbaConfig()
        assert config.get_result_chart_name() == "sba_standard_v1"

    def test_sba_supports_auto_mode(self):
        """SBA does not support auto mode (cards not digitized)."""
        config = SbaConfig()
        assert config.supports_auto_mode() is False

    def test_sba_api_url(self):
        """SBA API URL is correct."""
        config = SbaConfig()
        assert config.get_api_base_url() == "https://api.sba.manticorum.com"

    def test_sba_player_selection_mode(self):
        """SBA uses manual player selection."""
        config = SbaConfig()
        assert config.player_selection_mode == "manual"

    def test_sba_config_is_immutable(self):
        """Config cannot be modified after creation."""
        config = SbaConfig()
        with pytest.raises(ValidationError):
            config.innings = 7


class TestPdConfig:
    """Tests for PD league configuration."""

    def test_pd_config_creation(self):
        """Can create PD config instance."""
        config = PdConfig()
        assert config.league_id == "pd"
        assert config.version == "1.0.0"

    def test_pd_basic_rules(self):
        """PD uses standard baseball rules."""
        config = PdConfig()
        assert config.innings == 9
        assert config.outs_per_inning == 3

    def test_pd_result_chart_name(self):
        """PD uses pd_standard_v1 chart."""
        config = PdConfig()
        assert config.get_result_chart_name() == "pd_standard_v1"

    def test_pd_supports_auto_mode(self):
        """PD supports auto mode (digitized card data)."""
        config = PdConfig()
        assert config.supports_auto_mode() is True

    def test_pd_api_url(self):
        """PD API URL is correct."""
        config = PdConfig()
        assert config.get_api_base_url() == "https://pd.manticorum.com/api/"

    def test_pd_player_selection_mode(self):
        """PD uses flexible player selection."""
        config = PdConfig()
        assert config.player_selection_mode == "flexible"

    def test_pd_scouting_model_enabled(self):
        """PD has scouting model enabled."""
        config = PdConfig()
        assert config.use_scouting_model is True

    def test_pd_cardset_validation_enabled(self):
        """PD has cardset validation enabled."""
        config = PdConfig()
        assert config.cardset_validation is True

    def test_pd_advanced_analytics_enabled(self):
        """PD has advanced analytics enabled."""
        config = PdConfig()
        assert config.detailed_analytics is True
        assert config.wpa_calculation is True

    def test_pd_config_is_immutable(self):
        """Config cannot be modified after creation."""
        config = PdConfig()
        with pytest.raises(ValidationError):
            config.use_scouting_model = False


class TestLeagueRegistry:
    """Tests for league config registry and getter."""

    def test_registry_contains_both_leagues(self):
        """Registry has both SBA and PD configs."""
        assert "sba" in LEAGUE_CONFIGS
        assert "pd" in LEAGUE_CONFIGS
        assert len(LEAGUE_CONFIGS) == 2

    def test_registry_configs_are_correct_type(self):
        """Registry contains correct config types."""
        assert isinstance(LEAGUE_CONFIGS["sba"], SbaConfig)
        assert isinstance(LEAGUE_CONFIGS["pd"], PdConfig)

    def test_get_sba_config(self):
        """Can get SBA config via getter."""
        config = get_league_config("sba")
        assert isinstance(config, SbaConfig)
        assert config.league_id == "sba"

    def test_get_pd_config(self):
        """Can get PD config via getter."""
        config = get_league_config("pd")
        assert isinstance(config, PdConfig)
        assert config.league_id == "pd"

    def test_get_invalid_league_raises(self):
        """Getting invalid league raises ValueError."""
        with pytest.raises(ValueError) as exc_info:
            get_league_config("invalid")
        assert "Unknown league: invalid" in str(exc_info.value)
        assert "sba" in str(exc_info.value)
        assert "pd" in str(exc_info.value)

    def test_registry_returns_same_instance(self):
        """Registry returns singleton instances."""
        config1 = get_league_config("sba")
        config2 = get_league_config("sba")
        assert config1 is config2


class TestConfigDifferences:
    """Tests for differences between league configs."""

    def test_different_result_charts(self):
        """SBA and PD use different result charts."""
        sba = get_league_config("sba")
        pd = get_league_config("pd")
        assert sba.get_result_chart_name() != pd.get_result_chart_name()

    def test_different_api_urls(self):
        """SBA and PD have different API URLs."""
        sba = get_league_config("sba")
        pd = get_league_config("pd")
        assert sba.get_api_base_url() != pd.get_api_base_url()

    def test_different_player_selection_modes(self):
        """SBA and PD have different selection modes."""
        sba = get_league_config("sba")
        pd = get_league_config("pd")
        assert sba.player_selection_mode == "manual"
        assert pd.player_selection_mode == "flexible"

    def test_pd_has_extra_features(self):
        """PD has features that SBA doesn't."""
        pd = get_league_config("pd")
        sba = get_league_config("sba")

        # PD-specific attributes
        assert hasattr(pd, 'use_scouting_model')
        assert hasattr(pd, 'cardset_validation')
        assert hasattr(pd, 'detailed_analytics')

        # SBA doesn't have these (or they're False/None)
        assert not hasattr(sba, 'use_scouting_model')
        assert not hasattr(sba, 'cardset_validation')
