# tests/test_agent_loop_metadata.py
import pytest
from pathlib import Path
from nanobot.agent.loop import AgentLoop
from nanobot.bus.queue import MessageBus
from nanobot.providers.base import LLMProvider, LLMResponse
from unittest.mock import AsyncMock, MagicMock


@pytest.mark.asyncio
async def test_process_direct_passes_metadata():
    """Test that process_direct passes metadata to InboundMessage."""
    bus = MessageBus()
    provider = MagicMock(spec=LLMProvider)
    provider.chat = AsyncMock(return_value=LLMResponse(
        content="test response",
        tool_calls=[]
    ))
    provider.get_default_model = MagicMock(return_value="test-model")
    provider.thinking_budget = 0

    workspace = Path("/tmp/test-workspace")
    workspace.mkdir(exist_ok=True)

    loop = AgentLoop(bus=bus, provider=provider, workspace=workspace)

    # Call with metadata
    test_metadata = {"suppress_output": True, "test_key": "test_value"}
    await loop.process_direct(
        content="test message",
        metadata=test_metadata
    )

    # Verify provider.chat was called
    assert provider.chat.called
    call_args = provider.chat.call_args
    messages = call_args.kwargs["messages"]

    # The user message should contain the content
    # (We can't easily check InboundMessage directly, but we verify
    # the flow worked by checking the session was created)
    session = loop.sessions.get_or_create("cli:direct")
    assert len(session.messages) > 0


@pytest.mark.asyncio
async def test_suppress_mode_adds_hidden_prefix():
    """Test that suppress_output metadata adds [HIDDEN:signature] prefix."""
    bus = MessageBus()
    provider = MagicMock(spec=LLMProvider)
    provider.chat = AsyncMock(return_value=LLMResponse(
        content="This is the agent response",
        tool_calls=[]
    ))
    provider.get_default_model = MagicMock(return_value="test-model")
    provider.thinking_budget = 0

    workspace = Path("/tmp/test-workspace")
    workspace.mkdir(exist_ok=True)

    loop = AgentLoop(bus=bus, provider=provider, workspace=workspace)

    # Call with suppress_output=True
    response = await loop.process_direct(
        content="test message",
        metadata={"suppress_output": True}
    )

    # Response content should have [HIDDEN:signature] prefix with 8-char hex signature
    assert response.startswith("[HIDDEN:")
    assert "]" in response
    # Extract signature part between [HIDDEN: and ]
    prefix_end = response.index("]")
    signature = response[8:prefix_end]  # Skip "[HIDDEN:" to get signature
    assert len(signature) == 8  # 8-character hex signature
    assert all(c in "0123456789abcdef" for c in signature)  # Valid hex
    assert "This is the agent response" in response


@pytest.mark.asyncio
async def test_normal_mode_no_hidden_prefix():
    """Test that normal messages don't get [HIDDEN:signature] prefix."""
    bus = MessageBus()
    provider = MagicMock(spec=LLMProvider)
    provider.chat = AsyncMock(return_value=LLMResponse(
        content="Normal response",
        tool_calls=[]
    ))
    provider.get_default_model = MagicMock(return_value="test-model")
    provider.thinking_budget = 0

    workspace = Path("/tmp/test-workspace")
    workspace.mkdir(exist_ok=True)

    loop = AgentLoop(bus=bus, provider=provider, workspace=workspace)

    # Call without suppress_output
    response = await loop.process_direct(content="test message")

    # Response should NOT have [HIDDEN:signature] prefix
    assert not response.startswith("[HIDDEN:")
    assert response == "Normal response"
