from __future__ import annotations

import pytest

from rabbitmq_mcp.mcp_errors import MCPToolError
from rabbitmq_mcp.registry import get_operation
from rabbitmq_mcp.safety import enforce_safety


class DummyClient:
    async def request(self, method: str, path: str, params=None, json_body=None):  # type: ignore[no-untyped-def]
        return {"messages": 1}


class ExchangeBindingClient:
    async def request(self, method: str, path: str, params=None, json_body=None):  # type: ignore[no-untyped-def]
        if "bindings/source" in path:
            return [{"source": "ex"}]
        if "bindings/destination" in path:
            return []
        return {}


@pytest.mark.asyncio
async def test_enforce_safety_requires_flag() -> None:
    operation = get_operation("queues.delete_by_params")
    with pytest.raises(MCPToolError) as excinfo:
        await enforce_safety(operation, DummyClient(), {"vhost": "/", "name": "q"}, False)
    assert excinfo.value.code == "DESTRUCTIVE_OPERATION"


@pytest.mark.asyncio
async def test_enforce_safety_queue_not_empty() -> None:
    operation = get_operation("queues.delete_by_params")
    with pytest.raises(MCPToolError) as excinfo:
        await enforce_safety(operation, DummyClient(), {"vhost": "/", "name": "q"}, True)
    assert excinfo.value.code == "QUEUE_NOT_EMPTY"


@pytest.mark.asyncio
async def test_enforce_safety_exchange_has_bindings() -> None:
    operation = get_operation("exchanges.delete_by_params")
    with pytest.raises(MCPToolError) as excinfo:
        await enforce_safety(
            operation,
            ExchangeBindingClient(),
            {"vhost": "/", "name": "ex"},
            True,
        )
    assert excinfo.value.code == "EXCHANGE_HAS_BINDINGS"
