"""Tests for tool middleware."""
import pytest
from logos_adk.types import ToolCall, ToolResult
from logos_adk.tools.middleware import ToolMiddlewareChain


async def execute_tool(call: ToolCall) -> ToolResult:
    """Fake tool executor."""
    return ToolResult(call_id=call.id, content=f"result for {call.name}")


@pytest.fixture
def chain():
    return ToolMiddlewareChain(executor=execute_tool)


@pytest.mark.asyncio
async def test_no_middleware(chain):
    call = ToolCall(id="1", name="search", arguments={"q": "test"})
    result = await chain.execute(call)
    assert result.content == "result for search"


@pytest.mark.asyncio
async def test_single_middleware(chain):
    log = []

    async def logging_mw(call: ToolCall, next_fn):
        log.append(f"before:{call.name}")
        result = await next_fn(call)
        log.append(f"after:{call.name}")
        return result

    chain.use(logging_mw)
    call = ToolCall(id="1", name="search", arguments={})
    result = await chain.execute(call)

    assert result.content == "result for search"
    assert log == ["before:search", "after:search"]


@pytest.mark.asyncio
async def test_middleware_order():
    order = []

    async def mw_a(call, next_fn):
        order.append("a_before")
        result = await next_fn(call)
        order.append("a_after")
        return result

    async def mw_b(call, next_fn):
        order.append("b_before")
        result = await next_fn(call)
        order.append("b_after")
        return result

    chain = ToolMiddlewareChain(executor=execute_tool)
    chain.use(mw_a)
    chain.use(mw_b)

    call = ToolCall(id="1", name="test", arguments={})
    await chain.execute(call)

    assert order == ["a_before", "b_before", "b_after", "a_after"]


@pytest.mark.asyncio
async def test_middleware_short_circuit():
    async def blocker(call: ToolCall, next_fn):
        return ToolResult(call_id=call.id, content="blocked", error="not allowed")

    chain = ToolMiddlewareChain(executor=execute_tool)
    chain.use(blocker)

    call = ToolCall(id="1", name="search", arguments={})
    result = await chain.execute(call)
    assert result.error == "not allowed"
    assert result.content == "blocked"


@pytest.mark.asyncio
async def test_tool_execute_as_middleware_executor():
    """Integration: Tool.execute() is compatible with ToolMiddlewareChain executor."""
    from logos_adk.tools import tool

    @tool
    async def add(a: int, b: int) -> int:
        """Add two numbers."""
        return a + b

    chain = ToolMiddlewareChain(executor=add.execute)
    call = ToolCall(id="1", name="add", arguments={"a": 2, "b": 3})
    result = await chain.execute(call)
    assert result.content == 5
    assert result.error is None
    assert result.duration_ms > 0
