from __future__ import annotations

import asyncio
import types
import unittest

from bridge.config import LocalServerConfig
from bridge.server_manager import LocalMCPServerConnection, MAX_INFLIGHT_PER_SERVER


class LocalServerManagerConcurrencyTests(unittest.IsolatedAsyncioTestCase):
    async def test_inflight_limit_enforced(self) -> None:
        conn = LocalMCPServerConnection(
            LocalServerConfig(
                name="test-http",
                transport="http",
                url="http://localhost:3001/mcp",
            )
        )
        conn._started = True

        async def fake_send_http(self, payload):
            await asyncio.sleep(0.05)
            return {"jsonrpc": "2.0", "id": payload.get("id"), "result": {"ok": True}}

        conn._send_http = types.MethodType(fake_send_http, conn)

        async def send_one(i: int):
            return await conn.send_jsonrpc(
                {"jsonrpc": "2.0", "id": f"req-{i}", "method": "tools/list", "params": {}}
            )

        tasks = [asyncio.create_task(send_one(i)) for i in range(MAX_INFLIGHT_PER_SERVER + 1)]
        results = await asyncio.gather(*tasks, return_exceptions=True)

        overload_errors = [
            item
            for item in results
            if isinstance(item, RuntimeError) and "overloaded" in str(item).lower()
        ]
        self.assertTrue(
            overload_errors,
            "Expected at least one overload RuntimeError when in-flight limit is exceeded.",
        )
