"""Tests for DelegationManager — creation, acceptance, revocation."""

import pytest
from unittest.mock import MagicMock
from web3 import Web3

from vkp.delegation import DelegationManager, DelegationInfo


@pytest.fixture
def manager():
    """Create a DelegationManager with mock Web3."""
    w3 = MagicMock(spec=Web3)
    w3.eth = MagicMock()
    return DelegationManager(w3, "base-mainnet", "0x1234567890123456789012345678901234567890")


@pytest.fixture
def manager_no_address():
    """Create a DelegationManager without registry address."""
    w3 = MagicMock(spec=Web3)
    return DelegationManager(w3, "base-mainnet")


def test_create_delegation_requires_address(manager_no_address):
    """Test delegation creation fails without registry address."""
    with pytest.raises(ValueError, match="not configured"):
        manager_no_address.create_delegation(
            from_address="0x1234567890123456789012345678901234567890",
            delegate="0x2345678901234567890123456789012345678901",
        )


def test_create_delegation_returns_unsigned_tx(manager):
    """Test delegation creation returns an unsigned transaction."""
    result = manager.create_delegation(
        from_address="0x1234567890123456789012345678901234567890",
        delegate="0x2345678901234567890123456789012345678901",
        max_value="0.1",
        total_limit="1.0",
        duration_hours=48,
        min_bond="0.01",
        min_reputation=50,
    )
    assert "unsigned_tx" in result
    assert "delegation" in result["description"].lower()


def test_create_delegation_with_contract_allowlist(manager):
    """Test delegation with specific contracts allowed."""
    result = manager.create_delegation(
        from_address="0x1234567890123456789012345678901234567890",
        delegate="0x2345678901234567890123456789012345678901",
        allowed_contracts=["0xABCDEF0123456789012345678901234567890123"],
    )
    assert "unsigned_tx" in result


def test_accept_delegation_returns_unsigned_tx(manager):
    """Test accepting a delegation returns an unsigned transaction."""
    result = manager.accept_delegation(
        from_address="0x2345678901234567890123456789012345678901",
        delegation_id=7,
    )
    assert "unsigned_tx" in result
    assert "7" in result["description"]


def test_revoke_delegation_returns_unsigned_tx(manager):
    """Test revoking a delegation returns an unsigned transaction."""
    result = manager.revoke_delegation(
        from_address="0x1234567890123456789012345678901234567890",
        delegation_id=3,
    )
    assert "unsigned_tx" in result
    assert "3" in result["description"]


def test_revoke_all_returns_unsigned_tx(manager):
    """Test revoking all delegations returns an unsigned transaction."""
    result = manager.revoke_all(
        from_address="0x1234567890123456789012345678901234567890",
    )
    assert "unsigned_tx" in result
    assert "EMERGENCY" in result["description"]


def test_is_valid_requires_address(manager_no_address):
    """Test validity check fails without registry address."""
    with pytest.raises(ValueError, match="not configured"):
        manager_no_address.is_valid(delegation_id=1)


def test_delegation_info_dataclass():
    """Test DelegationInfo dataclass construction."""
    info = DelegationInfo(
        delegation_id=1,
        delegator="0xDelegator",
        delegate="0xDelegate",
        max_value_wei=10**17,
        total_limit_wei=10**18,
        total_spent_wei=0,
        remaining_wei=10**18,
        expires_at=1700000000,
        created_at=1699999000,
        min_bond_required=10**16,
        min_reputation=50,
        revoked=False,
        accepted=True,
        encrypted_key_hash=b"\x00" * 32,
    )
    assert info.delegation_id == 1
    assert info.accepted
    assert not info.revoked
    assert info.min_reputation == 50
