import pytest
from unittest.mock import patch, MagicMock, call
import httpx
import asyncio

from app.services.ai_engine.base import AIEngineAdapter, EngineType


class TestBatchQueryExceptionHandling:
    """测试 batch_query.py 中的异常处理行为"""

    def test_build_adapters_handles_generic_exception(self, caplog):
        """测试 _build_adapters 对通用异常的处理（应记录 error 日志）"""
        from app.services.ai_engine.batch_query import _build_adapters, _ADAPTER_CLASSES

        class FailingAdapter(AIEngineAdapter):
            def __init__(self):
                super().__init__(api_key="test")
                raise RuntimeError("Simulated initialization failure")

            def get_engine_type(self):
                return EngineType.CHATGPT

            def _get_env_key(self):
                return "TEST_KEY"

            async def query(self, query, brand_name, competitor_names=None):
                pass

        with patch.dict(_ADAPTER_CLASSES, {EngineType.CHATGPT: FailingAdapter}):
            _build_adapters.cache_clear()
            result = _build_adapters()
            assert EngineType.CHATGPT.value not in result

    def test_build_adapters_handles_httpx_http_error(self, caplog):
        """测试 _build_adapters 对 httpx.HTTPError 的处理（应记录 warning 日志）"""
        from app.services.ai_engine.batch_query import _build_adapters, _ADAPTER_CLASSES

        class HttpErrorAdapter(AIEngineAdapter):
            def __init__(self):
                super().__init__(api_key="test")
                raise httpx.HTTPError("HTTP connection failed")

            def get_engine_type(self):
                return EngineType.PERPLEXITY

            def _get_env_key(self):
                return "TEST_KEY"

            async def query(self, query, brand_name, competitor_names=None):
                pass

        with patch.dict(_ADAPTER_CLASSES, {EngineType.PERPLEXITY: HttpErrorAdapter}):
            _build_adapters.cache_clear()
            result = _build_adapters()
            assert EngineType.PERPLEXITY.value not in result
            assert any("HTTP error" in record.message for record in caplog.records)

    def test_build_adapters_handles_timeout_error(self, caplog):
        """测试 _build_adapters 对 asyncio.TimeoutError 的处理（应记录 warning 日志）"""
        from app.services.ai_engine.batch_query import _build_adapters, _ADAPTER_CLASSES

        class TimeoutAdapter(AIEngineAdapter):
            def __init__(self):
                super().__init__(api_key="test")
                raise asyncio.TimeoutError("Connection timeout")

            def get_engine_type(self):
                return EngineType.KIMI

            def _get_env_key(self):
                return "TEST_KEY"

            async def query(self, query, brand_name, competitor_names=None):
                pass

        with patch.dict(_ADAPTER_CLASSES, {EngineType.KIMI: TimeoutAdapter}):
            _build_adapters.cache_clear()
            result = _build_adapters()
            assert EngineType.KIMI.value not in result
            assert any("Timeout" in record.message for record in caplog.records)

    def test_build_adapters_with_key_manager_handles_httpx_http_error(self, caplog):
        """测试 _build_adapters_with_key_manager 对 httpx.HTTPError 的处理"""
        from app.services.ai_engine.batch_query import _build_adapters_with_key_manager, _ADAPTER_CLASSES

        class HttpErrorAdapter(AIEngineAdapter):
            def __init__(self, key_manager=None, user_id=None):
                super().__init__(api_key="test")
                raise httpx.HTTPError("HTTP connection failed")

            def get_engine_type(self):
                return EngineType.WENXIN

            def _get_env_key(self):
                return "TEST_KEY"

            async def query(self, query, brand_name, competitor_names=None):
                pass

        with patch.dict(_ADAPTER_CLASSES, {EngineType.WENXIN: HttpErrorAdapter}):
            result = _build_adapters_with_key_manager(
                key_manager=MagicMock(),
                user_id="test_user"
            )
            assert EngineType.WENXIN.value not in result
            assert any("HTTP error" in record.message for record in caplog.records)

    def test_build_adapters_with_key_manager_handles_timeout_error(self, caplog):
        """测试 _build_adapters_with_key_manager 对 asyncio.TimeoutError 的处理"""
        from app.services.ai_engine.batch_query import _build_adapters_with_key_manager, _ADAPTER_CLASSES

        class TimeoutAdapter(AIEngineAdapter):
            def __init__(self, key_manager=None, user_id=None):
                super().__init__(api_key="test")
                raise asyncio.TimeoutError("Connection timeout")

            def get_engine_type(self):
                return EngineType.DEEPSEEK

            def _get_env_key(self):
                return "TEST_KEY"

            async def query(self, query, brand_name, competitor_names=None):
                pass

        with patch.dict(_ADAPTER_CLASSES, {EngineType.DEEPSEEK: TimeoutAdapter}):
            result = _build_adapters_with_key_manager(
                key_manager=MagicMock(),
                user_id="test_user"
            )
            assert EngineType.DEEPSEEK.value not in result
            assert any("Timeout" in record.message for record in caplog.records)

    def test_build_adapters_with_key_manager_handles_generic_exception(self, caplog):
        """测试 _build_adapters_with_key_manager 对通用异常的处理"""
        from app.services.ai_engine.batch_query import _build_adapters_with_key_manager, _ADAPTER_CLASSES

        class FailingAdapter(AIEngineAdapter):
            def __init__(self, key_manager=None, user_id=None):
                super().__init__(api_key="test")
                raise RuntimeError("Simulated key manager failure")

            def get_engine_type(self):
                return EngineType.QWEN

            def _get_env_key(self):
                return "TEST_KEY"

            async def query(self, query, brand_name, competitor_names=None):
                pass

        with patch.dict(_ADAPTER_CLASSES, {EngineType.QWEN: FailingAdapter}):
            result = _build_adapters_with_key_manager(
                key_manager=MagicMock(),
                user_id="test_user"
            )
            assert EngineType.QWEN.value not in result

    def test_register_adapter_handles_exception(self):
        """测试 register_adapter 函数对异常的处理"""
        from app.services.ai_engine.batch_query import register_adapter

        class BadAdapter(AIEngineAdapter):
            def __init__(self):
                super().__init__(api_key="test")
                raise ValueError("Adapter registration failed")

            def get_engine_type(self):
                return EngineType.GEMINI

            def _get_env_key(self):
                return "TEST_KEY"

            async def query(self, query, brand_name, competitor_names=None):
                pass

        register_adapter(BadAdapter)
