import pytest
from unittest.mock import patch, MagicMock
from agentmetrics import sentinel, Sentinel


def setup_function():
    sentinel._api_key = None
    sentinel._client = None


def test_no_op_when_not_configured():
    """Agent runs normally when sentinel is not configured."""
    @sentinel.track(agent_id="test")
    def my_agent():
        return "result"

    assert my_agent() == "result"


def test_tracks_success():
    sentinel.configure(api_key="test_key", base_url="http://localhost:8000/v1")

    sent = []
    sentinel._client.fire_and_forget = lambda payload: sent.append(payload)

    @sentinel.track(agent_id="test_agent")
    def my_agent():
        return "ok"

    result = my_agent()
    assert result == "ok"
    assert len(sent) == 1
    assert sent[0]["status"] == "success"
    assert sent[0]["agent_id"] == "test_agent"
    assert sent[0]["duration_ms"] >= 0


def test_tracks_failure():
    sentinel.configure(api_key="test_key", base_url="http://localhost:8000/v1")

    sent = []
    sentinel._client.fire_and_forget = lambda payload: sent.append(payload)

    @sentinel.track(agent_id="failing_agent")
    def my_agent():
        raise ValueError("something broke")

    with pytest.raises(ValueError):
        my_agent()

    assert len(sent) == 1
    assert sent[0]["status"] == "failed"
    assert "something broke" in sent[0]["error"]


@pytest.mark.asyncio
async def test_async_agent():
    sentinel.configure(api_key="test_key", base_url="http://localhost:8000/v1")

    sent = []
    sentinel._client.fire_and_forget = lambda payload: sent.append(payload)

    @sentinel.track(agent_id="async_agent")
    async def my_async_agent():
        return "async_result"

    result = await my_async_agent()
    assert result == "async_result"
    assert sent[0]["status"] == "success"


def test_never_raises_on_send_failure():
    sentinel.configure(api_key="test_key", base_url="http://unreachable:9999/v1")

    @sentinel.track(agent_id="test")
    def my_agent():
        return "fine"

    # Should not raise even though server is unreachable
    result = my_agent()
    assert result == "fine"
