import pytest
from ..models import Backend, ToolDefinition
from ..registry import Registry


@pytest.fixture
def backend():
    return Backend(id="backend_a", url="http://localhost:8001/sse")


@pytest.fixture
def tool_def():
    return ToolDefinition(
        name="get_weather",
        description="Returns current weather",
        input_schema={"type": "object", "properties": {"city": {"type": "string"}}},
    )


@pytest.fixture
def registry():
    return Registry()


def test_add_and_get_backend(registry, backend):
    registry.add_backend(backend)
    assert registry.get_backend("backend_a") == backend


def test_get_unknown_backend_raises(registry):
    with pytest.raises(KeyError):
        registry.get_backend("nonexistent")


def test_register_and_resolve_tool(registry, backend, tool_def):
    registry.add_backend(backend)
    registry.register_tool(backend, tool_def)

    mapping = registry.resolve("get_weather")
    assert mapping.public_name == "get_weather"
    assert mapping.original_name == "get_weather"
    assert mapping.backend == backend


def test_register_tool_with_custom_public_name(registry, backend, tool_def):
    registry.add_backend(backend)
    registry.register_tool(backend, tool_def, public_name="weather")

    mapping = registry.resolve("weather")
    assert mapping.public_name == "weather"
    assert mapping.original_name == "get_weather"


def test_resolve_unknown_tool_raises(registry):
    with pytest.raises(KeyError):
        registry.resolve("nonexistent")


def test_list_tools(registry, backend, tool_def):
    registry.add_backend(backend)
    registry.register_tool(backend, tool_def)

    tools = registry.list_tools()
    assert len(tools) == 1
    assert tools[0].public_name == "get_weather"


def test_remove_backend_clears_its_tools(registry, backend, tool_def):
    registry.add_backend(backend)
    registry.register_tool(backend, tool_def)

    registry.remove_backend("backend_a")

    assert registry.list_tools() == []
    with pytest.raises(KeyError):
        registry.get_backend("backend_a")


def test_tool_name_collision_raises(registry, tool_def):
    backend_a = Backend(id="a", url="http://localhost:8001/sse")
    backend_b = Backend(id="b", url="http://localhost:8002/sse")
    registry.add_backend(backend_a)
    registry.add_backend(backend_b)

    registry.register_tool(backend_a, tool_def)
    with pytest.raises(RuntimeError, match="collision"):
        registry.register_tool(backend_b, tool_def)

    mapping = registry.resolve("get_weather")
    assert mapping.backend.id == "a"


def test_same_backend_can_re_register_tool(registry, backend, tool_def):
    """Re-rejestracja przez ten sam backend (np. po refresh) nie rzuca."""
    registry.add_backend(backend)
    registry.register_tool(backend, tool_def)
    registry.register_tool(backend, tool_def)
    assert len(registry.list_tools()) == 1


def test_remove_backend_leaves_other_backends_tools(registry, tool_def):
    backend_a = Backend(id="a", url="http://localhost:8001/sse")
    backend_b = Backend(id="b", url="http://localhost:8002/sse")
    tool_b = ToolDefinition(name="other_tool", description="", input_schema={})

    registry.add_backend(backend_a)
    registry.add_backend(backend_b)
    registry.register_tool(backend_a, tool_def)
    registry.register_tool(backend_b, tool_b)

    registry.remove_backend("a")

    tools = registry.list_tools()
    assert len(tools) == 1
    assert tools[0].public_name == "other_tool"
