import asyncio
from types import SimpleNamespace
from unittest.mock import AsyncMock, patch

from app.agent import MoviePilotAgent
from app.runtime.config import settings
from app.schemas import AgentLLMProviderEventData
from app.schemas.types import ChainEventType


def test_resolve_llm_runtime_config_uses_system_thinking_level(monkeypatch) -> None:
    """插件未提供有效思考强度时应使用系统配置。"""
    monkeypatch.setattr(settings, "LLM_THINKING_LEVEL", "xhigh")
    agent = MoviePilotAgent(session_id="thinking-level-default", user_id="user-1")

    async def return_empty_config(event_type, event_data):
        """模拟插件未返回有效运行时配置。"""
        assert event_type == ChainEventType.AgentLLMProvider
        assert event_data.thinking_level == "xhigh"
        return SimpleNamespace(event_data=AgentLLMProviderEventData())

    with patch(
        "app.agent.orchestrator.eventmanager.async_send_event",
        new=AsyncMock(side_effect=return_empty_config),
    ):
        runtime_config = asyncio.run(agent._resolve_llm_runtime_config())

    assert runtime_config["thinking_level"] == "xhigh"


def test_resolve_llm_runtime_config_prefers_plugin_thinking_level(monkeypatch) -> None:
    """插件显式覆盖思考强度时应优先使用插件值。"""
    monkeypatch.setattr(settings, "LLM_THINKING_LEVEL", "xhigh")
    agent = MoviePilotAgent(session_id="thinking-level-plugin", user_id="user-1")

    async def override_thinking_level(_event_type, event_data):
        """模拟插件覆盖思考强度。"""
        event_data.thinking_level = "high"
        return SimpleNamespace(event_data=event_data)

    with patch(
        "app.agent.orchestrator.eventmanager.async_send_event",
        new=AsyncMock(side_effect=override_thinking_level),
    ):
        runtime_config = asyncio.run(agent._resolve_llm_runtime_config())

    assert runtime_config["thinking_level"] == "high"


def test_resolve_llm_runtime_config_uses_system_api_protocol(monkeypatch) -> None:
    """插件未提供 API 协议时应使用系统配置。"""
    monkeypatch.setattr(settings, "LLM_API_PROTOCOL", "responses")
    agent = MoviePilotAgent(session_id="api-protocol-default", user_id="user-1")

    async def return_empty_config(event_type, event_data):
        """模拟插件未返回有效运行时配置。"""
        assert event_type == ChainEventType.AgentLLMProvider
        assert event_data.api_protocol == "responses"
        return SimpleNamespace(event_data=AgentLLMProviderEventData())

    with patch(
        "app.agent.orchestrator.eventmanager.async_send_event",
        new=AsyncMock(side_effect=return_empty_config),
    ):
        runtime_config = asyncio.run(agent._resolve_llm_runtime_config())

    assert runtime_config["api_protocol"] == "responses"


def test_resolve_llm_runtime_config_prefers_plugin_api_protocol(monkeypatch) -> None:
    """插件显式覆盖 API 协议时应优先使用插件值。"""
    monkeypatch.setattr(settings, "LLM_API_PROTOCOL", "responses")
    agent = MoviePilotAgent(session_id="api-protocol-plugin", user_id="user-1")

    async def override_api_protocol(_event_type, event_data):
        """模拟插件覆盖 API 协议。"""
        event_data.api_protocol = "chat_completions"
        return SimpleNamespace(event_data=event_data)

    with patch(
        "app.agent.orchestrator.eventmanager.async_send_event",
        new=AsyncMock(side_effect=override_api_protocol),
    ):
        runtime_config = asyncio.run(agent._resolve_llm_runtime_config())

    assert runtime_config["api_protocol"] == "chat_completions"


def test_resolve_llm_runtime_config_prefers_plugin_web_search_mode(monkeypatch) -> None:
    """插件显式覆盖联网搜索模式时应优先使用插件值。"""
    monkeypatch.setattr(settings, "LLM_WEB_SEARCH_MODE", "local")
    agent = MoviePilotAgent(session_id="web-search-plugin", user_id="user-1")

    async def override_web_search_mode(_event_type, event_data):
        """模拟插件覆盖联网搜索模式。"""
        event_data.web_search_mode = "builtin"
        return SimpleNamespace(event_data=event_data)

    with patch(
        "app.agent.orchestrator.eventmanager.async_send_event",
        new=AsyncMock(side_effect=override_web_search_mode),
    ):
        runtime_config = asyncio.run(agent._resolve_llm_runtime_config())

    assert runtime_config["web_search_mode"] == "builtin"
