"""Tests for SwarmPay's high-level on-chain escrow flow."""

from swarmpay import OnchainEscrowConfig, SwarmPay, WebhookDispatcher


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_create_onchain_escrow_emits_event_and_returns_flow():
    config = OnchainEscrowConfig(
        chain_id=84532,
        contract_address="0xABCDEF1234567890ABCDEF1234567890ABCDEF12",
        token_address="0x3333333333333333333333333333333333333333",
        fee_recipient="0x4444444444444444444444444444444444444444",
        dispute_resolver="0x5555555555555555555555555555555555555555",
    )
    dispatcher = WebhookDispatcher()
    sp = SwarmPay(onchain_escrow_config=config, webhook_dispatcher=dispatcher)
    wallet = sp.create_wallet("buyer")
    wallet._provider = MockProvider("0x1111111111111111111111111111111111111111")
    wallet._address = wallet._provider.address

    result = sp.create_onchain_escrow(
        buyer_wallet=wallet,
        provider_wallet="0x2222222222222222222222222222222222222222",
        amount_usd=1.0,
        service_type="translation",
        escrow_nonce=12,
        timeout_seconds=600,
        reference="job-12",
        salt="abc",
    )

    assert result.escrow.escrow_id.endswith(":12")
    assert result.approval_tx_hash == "0xTX1"
    assert result.funding_tx_hash == "0xTX2"
    assert dispatcher.events[-1].event_type == "escrow.funded"
    assert dispatcher.events[-1].payload["escrow_id"] == result.escrow.escrow_id


def test_buy_service_onchain_escrow_funds_selected_provider():
    config = OnchainEscrowConfig(
        chain_id=84532,
        contract_address="0xABCDEF1234567890ABCDEF1234567890ABCDEF12",
        token_address="0x3333333333333333333333333333333333333333",
        fee_recipient="0x4444444444444444444444444444444444444444",
        dispute_resolver="0x5555555555555555555555555555555555555555",
    )
    sp = SwarmPay(onchain_escrow_config=config)
    wallet = sp.create_wallet("buyer")
    wallet._provider = MockProvider("0x1111111111111111111111111111111111111111")
    wallet._address = wallet._provider.address

    provider_wallet = sp.create_wallet("provider")
    provider_wallet._provider = MockProvider("0x2222222222222222222222222222222222222222")
    provider_wallet._address = provider_wallet._provider.address
    sp.register_service(provider_wallet, "translation", 0.5, "Translate text")

    result = sp.buy_service_onchain_escrow(wallet, "translation", escrow_nonce=3)

    assert result["provider"]["wallet"] == "0x2222222222222222222222222222222222222222"
    assert result["escrow"].escrow_id.endswith(":3")
    assert result["transactions"].funding_tx_hash == "0xTX2"


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

    delivered = sp.confirm_onchain_delivery(wallet, escrow_nonce=9)
    released = sp.release_onchain_escrow(wallet, escrow_nonce=9)
    refunded = sp.refund_onchain_escrow(wallet, escrow_nonce=9)
    disputed = sp.dispute_onchain_escrow(wallet, escrow_nonce=9, reason="bad quality")

    assert delivered.status.value == "delivered"
    assert released.status.value == "released"
    assert refunded.status.value == "refunded"
    assert disputed.status.value == "disputed"
    assert dispatcher.events[-1].event_type == "escrow.disputed"
    assert dispatcher.events[-1].payload["reason"] == "bad quality"
