"""Tests for the MCP Bridge plugin."""

from __future__ import annotations

from typing import Any

from agent_scout.plugins.base import PluginParam, ToolSpec
from agent_scout.plugins.mcp_bridge import MCPBridgePlugin, MCPServerConnection

# --- Mock server ---


class MockMCPServer(MCPServerConnection):
    """MCP server that doesn't make real HTTP calls."""

    def __init__(
        self,
        name: str = "test_server",
        tools: list[ToolSpec] | None = None,
        call_result: str = "mock result",
        call_fail: bool = False,
    ) -> None:
        super().__init__(name=name, endpoint="http://localhost:9999")
        self.tools = tools or []
        self._call_result = call_result
        self._call_fail = call_fail

    async def discover_tools(self) -> list[ToolSpec]:
        return self.tools

    async def call_tool(self, original_tool_name: str, tool_input: dict[str, Any]) -> str:
        if self._call_fail:
            return "MCP tool call failed: simulated error"
        return self._call_result


# --- Tests ---


async def test_execute_tool():
    plugin = MCPBridgePlugin()
    await plugin.load()
    await plugin.enable()

    server = MockMCPServer(
        name="srv",
        tools=[
            ToolSpec(
                name="mcp_srv_search",
                description="Search tool",
                parameters=[PluginParam(name="query", description="Query", required=True)],
            )
        ],
        call_result="Found 3 results",
    )
    plugin.add_server(server)

    result = await plugin.execute("mcp_srv_search", {"query": "test"})
    assert result == "Found 3 results"


async def test_execute_unknown_tool():
    plugin = MCPBridgePlugin()
    await plugin.load()
    await plugin.enable()

    result = await plugin.execute("mcp_unknown_tool", {})
    assert "Unknown MCP tool" in result


async def test_execute_disabled_server():
    plugin = MCPBridgePlugin()
    await plugin.load()
    await plugin.enable()

    server = MockMCPServer(
        name="disabled",
        tools=[ToolSpec(name="mcp_disabled_search", description="Search")],
    )
    server.enabled = False
    plugin.add_server(server)

    result = await plugin.execute("mcp_disabled_search", {})
    # Tool is mapped but server is disabled
    assert "disabled" in result


async def test_get_tools():
    plugin = MCPBridgePlugin()
    await plugin.load()
    await plugin.enable()

    server = MockMCPServer(
        name="srv",
        tools=[
            ToolSpec(name="mcp_srv_a", description="Tool A"),
            ToolSpec(name="mcp_srv_b", description="Tool B"),
        ],
    )
    plugin.add_server(server)

    tools = plugin.get_tools()
    assert len(tools) == 2
    names = {t.name for t in tools}
    assert "mcp_srv_a" in names
    assert "mcp_srv_b" in names


async def test_get_tools_excludes_disabled():
    plugin = MCPBridgePlugin()
    await plugin.load()
    await plugin.enable()

    enabled_srv = MockMCPServer(
        name="enabled", tools=[ToolSpec(name="mcp_enabled_a", description="A")]
    )
    disabled_srv = MockMCPServer(
        name="disabled", tools=[ToolSpec(name="mcp_disabled_b", description="B")]
    )
    disabled_srv.enabled = False

    plugin.add_server(enabled_srv)
    plugin.add_server(disabled_srv)

    tools = plugin.get_tools()
    assert len(tools) == 1
    assert tools[0].name == "mcp_enabled_a"


async def test_tool_call_failure():
    plugin = MCPBridgePlugin()
    await plugin.load()
    await plugin.enable()

    server = MockMCPServer(
        name="fail",
        tools=[ToolSpec(name="mcp_fail_search", description="Search")],
        call_fail=True,
    )
    plugin.add_server(server)

    result = await plugin.execute("mcp_fail_search", {"q": "test"})
    assert "failed" in result


async def test_health_check():
    plugin = MCPBridgePlugin()
    assert await plugin.health_check() is False

    await plugin.load()
    await plugin.enable()
    # No servers — not healthy
    assert await plugin.health_check() is False

    plugin.add_server(MockMCPServer(name="srv"))
    assert await plugin.health_check() is True


async def test_unload_clears_state():
    plugin = MCPBridgePlugin()
    await plugin.load()
    await plugin.enable()

    plugin.add_server(
        MockMCPServer(name="srv", tools=[ToolSpec(name="mcp_srv_t", description="T")])
    )
    assert len(plugin.get_tools()) == 1

    await plugin.unload()
    assert len(plugin._servers) == 0
    assert len(plugin._tool_to_server) == 0


async def test_plugin_metadata():
    plugin = MCPBridgePlugin()
    assert plugin.name == "mcp_bridge"
    assert "MCP" in plugin.description
