from __future__ import annotations

import httpx
import pytest
import respx

from bob import BoBClient


def test_agent_credit_raises_deprecation_error() -> None:
    client = BoBClient(api_key="bok_test", agent_id="agent-1")
    with pytest.raises(RuntimeError, match="removed"):
        client.get_agent_credit()
    client.close()


@respx.mock
def test_agent_credit_events_parses_response() -> None:
    route = respx.get(
        "https://api.bankofbots.ai/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(
        "https://api.bankofbots.ai/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(
        "https://api.bankofbots.ai/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(
        "https://api.bankofbots.ai/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(
        "https://api.bankofbots.ai/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(
        "https://api.bankofbots.ai/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(
        "https://api.bankofbots.ai/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(RuntimeError, match="removed"):
        client.get_agent_credit()
    client.close()


@respx.mock
def test_score_wallet_binding_x402_and_credential_methods() -> None:
    score_route = respx.get("https://api.bankofbots.ai/api/v1/score/me").mock(
        return_value=httpx.Response(200, json={"score": 410, "tier": "Verified", "tier_color": "green", "signals": []})
    )
    composition_route = respx.get("https://api.bankofbots.ai/api/v1/score/me/composition").mock(
        return_value=httpx.Response(200, json={"score": 410, "tier": "Verified", "tier_color": "green", "breakdown": [], "quick_wins": []})
    )
    visibility_route = respx.patch("https://api.bankofbots.ai/api/v1/score/me/signals/visibility").mock(
        return_value=httpx.Response(200, json={"signal_type": "github", "is_public": True})
    )
    leaderboard_route = respx.get("https://api.bankofbots.ai/api/v1/score/leaderboard", params={"limit": "10"}).mock(
        return_value=httpx.Response(200, json={"mode": "public", "entries": [], "self": None})
    )
    challenge_route = respx.post("https://api.bankofbots.ai/api/v1/operators/me/wallet-bindings/evm/challenge").mock(
        return_value=httpx.Response(200, json={"challenge_id": "chal_1", "message": "sign me", "expires_at": "2026-03-18T00:00:00Z"})
    )
    verify_route = respx.post("https://api.bankofbots.ai/api/v1/operators/me/wallet-bindings/evm/verify").mock(
        return_value=httpx.Response(200, json={"verified": True, "signal_type": "evm_wallet", "points_base": 20})
    )
    x402_route = respx.post("https://api.bankofbots.ai/api/v1/agents/agent-1/credit/imports/x402-receipts").mock(
        return_value=httpx.Response(201, json={"id": "imp_1", "verification_status": "verified", "credit": {"awarded": True, "delta": 5}})
    )
    issue_credential_route = respx.post("https://api.bankofbots.ai/api/v1/operators/me/credential").mock(
        return_value=httpx.Response(201, json={"id": "cred_1"})
    )
    get_credential_route = respx.get("https://api.bankofbots.ai/api/v1/operators/me/credential").mock(
        return_value=httpx.Response(200, json={"id": "cred_1"})
    )
    verify_credential_route = respx.get("https://api.bankofbots.ai/api/v1/credentials/cred_1").mock(
        return_value=httpx.Response(200, json={"valid": True, "credential": {"id": "cred_1"}})
    )

    client = BoBClient(api_key="bok_test", agent_id="agent-1")
    assert client.get_score()["score"] == 410
    assert client.get_score_composition()["tier"] == "Verified"
    assert client.update_signal_visibility("github", True)["is_public"] is True
    assert client.get_leaderboard(limit=10)["mode"] == "public"
    assert client.create_wallet_binding_challenge(address="0xabc")["challenge_id"] == "chal_1"
    assert client.verify_wallet_binding("chal_1", "0xabc", "0xsig")["verified"] is True
    assert client.import_x402_receipt("0xtx", "eip155:8453", "0xpayer", "0xpayee", "1000000")["id"] == "imp_1"
    assert client.issue_credential()["id"] == "cred_1"
    assert client.get_credential()["id"] == "cred_1"
    assert client.verify_credential("cred_1")["valid"] is True
    client.close()

    assert score_route.called
    assert composition_route.called
    assert visibility_route.called
    assert leaderboard_route.called
    assert challenge_route.called
    assert verify_route.called
    assert x402_route.called
    assert issue_credential_route.called
    assert get_credential_route.called
    assert verify_credential_route.called
