from __future__ import annotations

import httpx
import pytest
import respx

from bob import BoBClient


@respx.mock
def test_agent_credit_parses_response() -> None:
    route = respx.get(
        "http://localhost:8080/api/v1/agents/agent-1/credit"
    ).mock(
        return_value=httpx.Response(
            200,
            json={
                "agent_id": "agent-1",
                "score": 75,
                "tier": "growing",
                "reason": "good history",
                "base_spend_limit": 10000,
                "effective_spend_limit": 12000,
                "base_rate_limit": 20,
                "effective_rate_limit": 24,
                "tier_multiplier": 1.2,
                "credit_tier_enabled": True,
                "snapshot_at": "2026-02-27T00:00:00Z",
            },
        )
    )

    client = BoBClient(api_key="bok_test", agent_id="agent-1")
    resp = client.get_agent_credit()
    client.close()

    assert route.called
    assert resp.agent_id == "agent-1"
    assert resp.score == 75
    assert resp.tier == "growing"
    assert resp.effective_spend_limit == 12000
    assert resp.tier_multiplier == 1.2
    assert resp.credit_tier_enabled is True


@respx.mock
def test_agent_credit_events_parses_response() -> None:
    route = respx.get(
        "http://localhost:8080/api/v1/agents/agent-1/credit/events",
        params={"limit": "50", "offset": "0"},
    ).mock(
        return_value=httpx.Response(
            200,
            json={
                "data": [
                    {
                        "id": "ev-1",
                        "agent_id": "agent-1",
                        "event_type": "tx.completed",
                        "score_delta": 1,
                        "amount": 5000,
                        "currency": "BTC",
                        "rail": "lightning",
                        "status": "complete",
                        "reason": "",
                        "metadata": "{}",
                        "created_at": "2026-02-27T00:00:00Z",
                    }
                ],
                "total": 1,
                "limit": 50,
                "offset": 0,
                "has_more": False,
                "truncated": False,
            },
        )
    )

    client = BoBClient(api_key="bok_test", agent_id="agent-1")
    events = client.list_agent_credit_events(limit=50, offset=0)
    client.close()

    assert route.called
    assert len(events) == 1
    assert events[0].event_type == "tx.completed"
    assert events[0].score_delta == 1


@respx.mock
def test_agent_webhook_and_events_methods_parse_response() -> None:
    create_route = respx.post(
        "http://localhost:8080/api/v1/agents/agent-1/webhooks"
    ).mock(
        return_value=httpx.Response(
            201,
            json={
                "id": "wh-1",
                "operator_id": "op-1",
                "agent_id": "agent-1",
                "url": "https://example.com/hook",
                "events": ["payment_intent.complete"],
                "secret": "sec_abc",
                "active": True,
                "failure_count": 0,
                "created_at": "2026-03-01T00:00:00Z",
            },
        )
    )
    list_route = respx.get(
        "http://localhost:8080/api/v1/agents/agent-1/webhooks"
    ).mock(
        return_value=httpx.Response(
            200,
            json=[
                {
                    "id": "wh-1",
                    "operator_id": "op-1",
                    "agent_id": "agent-1",
                    "url": "https://example.com/hook",
                    "events": ["payment_intent.complete"],
                    "secret": "sec_abc",
                    "active": True,
                    "failure_count": 0,
                    "created_at": "2026-03-01T00:00:00Z",
                }
            ],
        )
    )
    events_route = respx.get(
        "http://localhost:8080/api/v1/agents/agent-1/events",
        params={"limit": "20", "offset": "5"},
    ).mock(
        return_value=httpx.Response(
            200,
            json={
                "data": [
                    {
                        "id": "evt-1",
                        "type": "payment_intent.complete",
                        "agent_id": "agent-1",
                        "operator_id": "op-1",
                        "payload": {"intent_id": "pi-1"},
                        "created_at": "2026-03-01T00:00:00Z",
                    }
                ],
                "total": 1,
                "limit": 20,
                "offset": 5,
                "has_more": False,
            },
        )
    )

    client = BoBClient(api_key="bok_test", agent_id="agent-1")
    created = client.create_agent_webhook("https://example.com/hook", events=["payment_intent.complete"])
    listed = client.list_agent_webhooks()
    events = client.list_agent_events(limit=20, offset=5)
    client.close()

    assert create_route.called
    assert list_route.called
    assert events_route.called
    assert created.agent_id == "agent-1"
    assert len(listed) == 1
    assert len(events) == 1
    assert events[0]["type"] == "payment_intent.complete"


@respx.mock
def test_operator_api_key_lifecycle_methods() -> None:
    create_route = respx.post(
        "http://localhost:8080/api/v1/operators/me/api-keys"
    ).mock(
        return_value=httpx.Response(
            201,
            json={
                "api_key": "bok_new_secret",
                "key": {
                    "id": "key-1",
                    "key_prefix": "bok_new_abc",
                    "operator_id": "op-1",
                    "role": "operator",
                    "scopes": ["operators:treasury:write"],
                    "name": "deploy key",
                    "created_at": "2026-02-27T00:00:00Z",
                },
            },
        )
    )
    list_route = respx.get(
        "http://localhost:8080/api/v1/operators/me/api-keys"
    ).mock(
        return_value=httpx.Response(
            200,
            json=[
                {
                    "id": "key-1",
                    "key_prefix": "bok_new_abc",
                    "operator_id": "op-1",
                    "role": "operator",
                    "scopes": ["operators:treasury:write"],
                    "name": "deploy key",
                    "created_at": "2026-02-27T00:00:00Z",
                }
            ],
        )
    )
    revoke_route = respx.post(
        "http://localhost:8080/api/v1/operators/me/api-keys/key-1/revoke"
    ).mock(
        return_value=httpx.Response(
            200,
            json={"status": "revoked", "id": "key-1"},
        )
    )

    client = BoBClient(api_key="bok_test")
    issued = client.create_api_key(name="deploy key", scopes=["operators:treasury:write"])
    listed = client.list_api_keys(limit=10)
    revoked = client.revoke_api_key("key-1")
    client.close()

    assert create_route.called
    assert list_route.called
    assert revoke_route.called
    assert issued["api_key"] == "bok_new_secret"
    assert issued["key"]["id"] == "key-1"
    assert len(listed) == 1
    assert listed[0].id == "key-1"
    assert revoked["status"] == "revoked"


def test_agent_calls_require_agent_id() -> None:
    client = BoBClient(api_key="bok_test")
    with pytest.raises(ValueError, match="agent_id is required"):
        client.get_agent_credit()
    client.close()
