"""Testy integracyjne RestApi — wymagają działającego serwera MCP."""

import pytest
from httpx import ASGITransport, AsyncClient

from ..connection_pool import ConnectionPool
from ..executor import Executor
from ..models import Backend, ToolDefinition
from ..registry import Registry
from ..rest_api import RestApi


@pytest.fixture
def registry(mcp_server_url):
    r = Registry()
    backend = Backend(id="test", url=mcp_server_url)
    r.add_backend(backend)
    for name, description, schema in [
        ("echo", "Zwraca podany tekst", {"type": "object", "properties": {"message": {"type": "string"}}, "required": ["message"]}),
        ("add", "Dodaje dwie liczby", {"type": "object", "properties": {"a": {"type": "integer"}, "b": {"type": "integer"}}, "required": ["a", "b"]}),
        ("fail", "Zawsze rzuca wyjątek", {"type": "object", "properties": {}}),
    ]:
        r.register_tool(backend, ToolDefinition(name=name, description=description, input_schema=schema))
    return r


@pytest.fixture
def pool():
    return ConnectionPool()


@pytest.fixture
def executor(pool):
    return Executor(pool)


@pytest.fixture
def api(registry, executor):
    return RestApi(registry, executor)


@pytest.fixture
def api_with_key(registry, executor):
    return RestApi(registry, executor, api_key="secret")


@pytest.mark.anyio
async def test_list_tools_returns_all_tools(api):
    async with AsyncClient(transport=ASGITransport(app=api.create_app()), base_url="http://test") as client:
        response = await client.get("/tools")
    assert response.status_code == 200
    names = [t["name"] for t in response.json()]
    assert "echo" in names
    assert "add" in names
    assert "fail" in names


@pytest.mark.anyio
async def test_list_tools_returns_schema(api):
    async with AsyncClient(transport=ASGITransport(app=api.create_app()), base_url="http://test") as client:
        response = await client.get("/tools")
    tools = {t["name"]: t for t in response.json()}
    assert "description" in tools["echo"]
    assert "input_schema" in tools["echo"]


@pytest.mark.anyio
async def test_call_tool_echo(api):
    async with AsyncClient(transport=ASGITransport(app=api.create_app()), base_url="http://test") as client:
        response = await client.post("/tools/echo", json={"message": "hello"})
    assert response.status_code == 200
    body = response.json()
    assert body["isError"] is False
    assert body["content"][0]["text"] == "hello"


@pytest.mark.anyio
async def test_call_tool_add(api):
    async with AsyncClient(transport=ASGITransport(app=api.create_app()), base_url="http://test") as client:
        response = await client.post("/tools/add", json={"a": 3, "b": 4})
    assert response.status_code == 200
    body = response.json()
    assert body["isError"] is False
    assert body["content"][0]["text"] == "7"


@pytest.mark.anyio
async def test_call_tool_error_returns_is_error(api):
    async with AsyncClient(transport=ASGITransport(app=api.create_app()), base_url="http://test") as client:
        response = await client.post("/tools/fail", json={})
    assert response.status_code == 200
    assert response.json()["isError"] is True


@pytest.mark.anyio
async def test_call_unknown_tool_returns_404(api):
    async with AsyncClient(transport=ASGITransport(app=api.create_app()), base_url="http://test") as client:
        response = await client.post("/tools/nonexistent", json={})
    assert response.status_code == 404


@pytest.mark.anyio
async def test_auth_required_when_api_key_set(api_with_key):
    app = api_with_key.create_app()
    async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client:
        response = await client.get("/tools")
    assert response.status_code == 401


@pytest.mark.anyio
async def test_auth_passes_with_correct_key(api_with_key):
    app = api_with_key.create_app()
    async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client:
        response = await client.get("/tools", headers={"X-API-Key": "secret"})
    assert response.status_code == 200


@pytest.mark.anyio
async def test_auth_fails_with_wrong_key(api_with_key):
    app = api_with_key.create_app()
    async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client:
        response = await client.post("/tools/echo", json={"message": "hi"}, headers={"X-API-Key": "wrong"})
    assert response.status_code == 401
