"""Tests for REST API helpers and on-chain endpoints."""

from swarmpay.api_server import (
    _build_onchain_escrow_config,
    _perform_onchain_action,
    _serialize_delivery,
    _serialize_subscription,
    _serialize_webhook_event,
)
from swarmpay import OnchainEscrowConfig, SwarmPay
from swarmpay.dashboard import build_dashboard_feed, build_dashboard_summary
from swarmpay.webhooks import WebhookDispatcher


def test_build_onchain_escrow_config_from_env(monkeypatch):
    monkeypatch.setenv("SWARMPAY_ESCROW_CONTRACT_ADDRESS", "0xABCDEF1234567890ABCDEF1234567890ABCDEF12")
    monkeypatch.setenv("SWARMPAY_ESCROW_TOKEN_ADDRESS", "0x3333333333333333333333333333333333333333")
    monkeypatch.setenv("SWARMPAY_ESCROW_FEE_RECIPIENT", "0x4444444444444444444444444444444444444444")
    monkeypatch.setenv("SWARMPAY_ESCROW_DISPUTE_RESOLVER", "0x5555555555555555555555555555555555555555")
    monkeypatch.setenv("SWARMPAY_CHAIN_ID", "84532")

    config = _build_onchain_escrow_config()

    assert config is not None
    assert config.chain_id == 84532
    assert config.contract_address == "0xABCDEF1234567890ABCDEF1234567890ABCDEF12"


def test_build_onchain_escrow_config_returns_none_when_incomplete(monkeypatch):
    monkeypatch.delenv("SWARMPAY_ESCROW_CONTRACT_ADDRESS", raising=False)
    monkeypatch.delenv("SWARMPAY_ESCROW_TOKEN_ADDRESS", raising=False)
    monkeypatch.delenv("SWARMPAY_ESCROW_FEE_RECIPIENT", raising=False)
    monkeypatch.delenv("SWARMPAY_ESCROW_DISPUTE_RESOLVER", raising=False)
    monkeypatch.delenv("SWARMPAY_CHAIN_ID", raising=False)

    assert _build_onchain_escrow_config() is None


def test_serialize_webhook_event_shape():
    dispatcher = WebhookDispatcher()
    event = dispatcher.emit("escrow.funded", {"escrow_id": "escrow:1"})

    data = _serialize_webhook_event(event)

    assert data["event_type"] == "escrow.funded"
    assert data["payload"]["escrow_id"] == "escrow:1"


def test_serialize_subscription_shape(tmp_path):
    dispatcher = WebhookDispatcher(storage_path=str(tmp_path / "webhooks.json"))
    subscription = dispatcher.subscribe("https://example.com/webhook", "secret123", ["escrow.funded"])

    data = _serialize_subscription(subscription)

    assert data["target_url"] == "https://example.com/webhook"
    assert data["event_types"] == ["escrow.funded"]


def test_serialize_delivery_shape(tmp_path):
    dispatcher = WebhookDispatcher(storage_path=str(tmp_path / "webhooks.json"))
    dispatcher.subscribe("https://example.com/webhook", "secret123")

    event = dispatcher.emit("escrow.funded", {"escrow_id": "escrow:1"})
    delivery = dispatcher.deliver_event(event, sender=lambda sub, evt: 200, now=100.0)[0]

    data = _serialize_delivery(delivery)

    assert data["event_id"] == event.event_id
    assert data["success"] is True


def test_dashboard_helpers_return_expected_shapes(tmp_path):
    dispatcher = WebhookDispatcher(storage_path=str(tmp_path / "webhooks.json"))
    dispatcher.subscribe("https://example.com/webhook", "secret123")
    event = dispatcher.emit("escrow.funded", {"escrow_id": "escrow:1"})
    dispatcher.deliver_event(event, sender=lambda sub, evt: 200, now=100.0)

    summary = build_dashboard_summary(dispatcher)
    feed = build_dashboard_feed(dispatcher, limit=5)

    assert "total_events" in summary
    assert "delivery_success_rate" in summary
    assert len(feed) >= 1


class _MockProvider:
    def __init__(self, address):
        self.address = address
        self.calls = []

    def get_address(self):
        return self.address

    def send_transaction(self, tx):
        self.calls.append(tx)
        return f"0xTX{len(self.calls)}"


def test_perform_onchain_action_release():
    config = OnchainEscrowConfig(
        chain_id=84532,
        contract_address="0xABCDEF1234567890ABCDEF1234567890ABCDEF12",
        token_address="0x3333333333333333333333333333333333333333",
        fee_recipient="0x4444444444444444444444444444444444444444",
        dispute_resolver="0x5555555555555555555555555555555555555555",
    )
    swarmpay = SwarmPay(onchain_escrow_config=config, webhook_dispatcher=WebhookDispatcher())
    wallet = swarmpay.create_wallet("buyer")
    wallet._provider = _MockProvider("0x1111111111111111111111111111111111111111")
    wallet._address = wallet._provider.address

    result = _perform_onchain_action(
        swarmpay,
        wallet,
        action="release",
        escrow_nonce=7,
        body={},
    )

    assert result["status"] == "released"
    assert result["escrow_id"].endswith(":7")


def test_perform_onchain_action_rejects_unknown_action():
    config = OnchainEscrowConfig(
        chain_id=84532,
        contract_address="0xABCDEF1234567890ABCDEF1234567890ABCDEF12",
        token_address="0x3333333333333333333333333333333333333333",
        fee_recipient="0x4444444444444444444444444444444444444444",
        dispute_resolver="0x5555555555555555555555555555555555555555",
    )
    swarmpay = SwarmPay(onchain_escrow_config=config, webhook_dispatcher=WebhookDispatcher())
    wallet = swarmpay.create_wallet("buyer")
    wallet._provider = _MockProvider("0x1111111111111111111111111111111111111111")
    wallet._address = wallet._provider.address

    try:
        _perform_onchain_action(
            swarmpay,
            wallet,
            action="unknown",
            escrow_nonce=7,
            body={},
        )
    except ValueError as exc:
        assert "Unsupported action" in str(exc)
    else:
        raise AssertionError("Expected unsupported action to raise ValueError")
