# tests/test_configuration.py
"""Tests for configuration validation at startup."""
import os
import pytest
from unittest.mock import patch
from pathlib import Path


class TestConfigurationValidation:
    """Tests for _validate_configuration() function."""

    def test_rejects_unknown_providers(self):
        """Should raise error for unknown providers in SECOND_OPINION_PROVIDERS."""
        from second_opinion_mcp.server import _validate_configuration

        with patch.dict(os.environ, {"SECOND_OPINION_PROVIDERS": "deepseek,invalid_provider"}):
            with pytest.raises(RuntimeError) as exc_info:
                _validate_configuration()

        assert "Unknown providers" in str(exc_info.value)
        assert "invalid_provider" in str(exc_info.value)

    def test_accepts_valid_providers(self):
        """Should accept valid provider names."""
        from second_opinion_mcp.server import _validate_configuration

        with patch.dict(os.environ, {"SECOND_OPINION_PROVIDERS": "deepseek,moonshot"}, clear=False):
            # Should not raise
            _validate_configuration()

    def test_accepts_kimi_alias(self):
        """Should accept 'kimi' as alias for moonshot."""
        from second_opinion_mcp.server import _validate_configuration

        with patch.dict(os.environ, {"SECOND_OPINION_PROVIDERS": "kimi"}, clear=False):
            # Should not raise
            _validate_configuration()

    def test_warns_on_nonexistent_allowed_root(self, caplog):
        """Should log warning for non-existent allowed roots."""
        from second_opinion_mcp.server import _validate_configuration

        with patch.dict(os.environ, {
            "SECOND_OPINION_ALLOWED_ROOTS": "/nonexistent/path/12345",
            "SECOND_OPINION_PROVIDERS": "",
        }):
            with caplog.at_level("WARNING"):
                _validate_configuration()

        assert "Allowed root does not exist" in caplog.text

    def test_rejects_invalid_moonshot_concurrent_value(self):
        """Should reject MOONSHOT_CONCURRENT outside valid range."""
        from second_opinion_mcp.server import _validate_configuration

        with patch.dict(os.environ, {"SECOND_OPINION_MOONSHOT_CONCURRENT": "100"}):
            with pytest.raises(RuntimeError) as exc_info:
                _validate_configuration()

        assert "MOONSHOT_CONCURRENT" in str(exc_info.value)

    def test_rejects_non_integer_moonshot_concurrent(self):
        """Should reject non-integer MOONSHOT_CONCURRENT."""
        from second_opinion_mcp.server import _validate_configuration

        with patch.dict(os.environ, {"SECOND_OPINION_MOONSHOT_CONCURRENT": "not_a_number"}):
            with pytest.raises(RuntimeError) as exc_info:
                _validate_configuration()

        assert "Invalid SECOND_OPINION_MOONSHOT_CONCURRENT" in str(exc_info.value)

    def test_rejects_invalid_moonshot_rpm_value(self):
        """Should reject MOONSHOT_RPM outside valid range."""
        from second_opinion_mcp.server import _validate_configuration

        with patch.dict(os.environ, {"SECOND_OPINION_MOONSHOT_RPM": "500"}):
            with pytest.raises(RuntimeError) as exc_info:
                _validate_configuration()

        assert "MOONSHOT_RPM" in str(exc_info.value)

    def test_accepts_valid_rate_limits(self):
        """Should accept valid rate limit values."""
        from second_opinion_mcp.server import _validate_configuration

        with patch.dict(os.environ, {
            "SECOND_OPINION_MOONSHOT_CONCURRENT": "5",
            "SECOND_OPINION_MOONSHOT_RPM": "50",
            "SECOND_OPINION_PROVIDERS": "",
        }):
            # Should not raise
            _validate_configuration()


class TestStructuredLogging:
    """Tests for _configure_logging() function."""

    def test_logging_disabled_by_default(self, caplog):
        """Logging should not be enabled unless SECOND_OPINION_LOG_ENABLED is set."""
        import logging
        from second_opinion_mcp.server import logger

        # Logger should have NullHandler by default
        has_null_handler = any(
            isinstance(h, logging.NullHandler)
            for h in logger.handlers
        )
        assert has_null_handler

    def test_logging_enabled_when_env_set(self):
        """Should configure logging when SECOND_OPINION_LOG_ENABLED is set."""
        from second_opinion_mcp.server import _configure_logging, logger
        import logging

        # Clear existing handlers for test
        original_handlers = logger.handlers.copy()
        logger.handlers = [logging.NullHandler()]

        try:
            with patch.dict(os.environ, {
                "SECOND_OPINION_LOG_ENABLED": "1",
                "SECOND_OPINION_LOG_LEVEL": "DEBUG",
            }):
                _configure_logging()

            # Should have added a StreamHandler
            has_stream_handler = any(
                isinstance(h, logging.StreamHandler)
                for h in logger.handlers
            )
            assert has_stream_handler
        finally:
            # Restore original handlers
            logger.handlers = original_handlers

    def test_respects_log_level_setting(self):
        """Should set log level from SECOND_OPINION_LOG_LEVEL."""
        from second_opinion_mcp.server import _configure_logging, logger
        import logging

        original_level = logger.level
        original_handlers = logger.handlers.copy()
        logger.handlers = [logging.NullHandler()]

        try:
            with patch.dict(os.environ, {
                "SECOND_OPINION_LOG_ENABLED": "1",
                "SECOND_OPINION_LOG_LEVEL": "ERROR",
            }):
                _configure_logging()

            assert logger.level == logging.ERROR
        finally:
            logger.level = original_level
            logger.handlers = original_handlers
