from __future__ import annotations

import json

import httpx
import pytest

from rabbitmq_mcp.client import RabbitMQClient, RabbitMQError
from rabbitmq_mcp.config import RabbitMQConfig


def make_config() -> RabbitMQConfig:
    return RabbitMQConfig(
        env="test",
        host="example",
        port=15672,
        amqp_port=5672,
        username="user",
        password="pass",
        vhost="/",
        scheme="http",
        verify_ssl=False,
        timeout=5.0,
        max_connections=5,
        max_keepalive_connections=5,
        retries=1,
        retry_backoff=0.1,
        vhost_cache_ttl=0.0,
        allow_destructive=False,
    )


@pytest.mark.asyncio
async def test_list_queues_vhost_encoded() -> None:
    async def handler(request: httpx.Request) -> httpx.Response:
        assert request.url.raw_path == b"/api/queues/%2F"
        return httpx.Response(200, json=[])

    transport = httpx.MockTransport(handler)
    async with httpx.AsyncClient(
        transport=transport, base_url="http://example/api", auth=("u", "p")
    ) as http_client:
        client = RabbitMQClient(config=make_config(), _client=http_client)
        result = await client.list_queues(vhost="/")
        assert result == []


@pytest.mark.asyncio
async def test_publish_payload_shape() -> None:
    async def handler(request: httpx.Request) -> httpx.Response:
        assert request.url.raw_path == b"/api/exchanges/%2F/amq.topic/publish"
        body = json.loads(request.content)
        assert body["routing_key"] == "rk"
        assert body["payload"] == "hello"
        assert body["payload_encoding"] == "string"
        return httpx.Response(200, json={"routed": True})

    transport = httpx.MockTransport(handler)
    async with httpx.AsyncClient(
        transport=transport, base_url="http://example/api", auth=("u", "p")
    ) as http_client:
        client = RabbitMQClient(config=make_config(), _client=http_client)
        result = await client.publish(
            vhost="/",
            exchange="amq.topic",
            routing_key="rk",
            payload="hello",
        )
        assert result == {"routed": True}


@pytest.mark.asyncio
async def test_http_error_raises_domain_error() -> None:
    async def handler(request: httpx.Request) -> httpx.Response:
        return httpx.Response(500, json={"error": "boom"})

    transport = httpx.MockTransport(handler)
    async with httpx.AsyncClient(
        transport=transport, base_url="http://example/api", auth=("u", "p")
    ) as http_client:
        client = RabbitMQClient(config=make_config(), _client=http_client)
        with pytest.raises(RabbitMQError):
            await client.list_vhosts()


@pytest.mark.asyncio
async def test_request_normalizes_api_prefix() -> None:
    async def handler(request: httpx.Request) -> httpx.Response:
        assert request.url.raw_path == b"/api/queues"
        return httpx.Response(200, json=[])

    transport = httpx.MockTransport(handler)
    async with httpx.AsyncClient(
        transport=transport, base_url="http://example/api", auth=("u", "p")
    ) as http_client:
        client = RabbitMQClient(config=make_config(), _client=http_client)
        result = await client.request("GET", "/api/queues")
        assert result == []
