"""Tests for KeyVaultManager — vault creation, status, policy enforcement."""

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

from vkp.keyvault import KeyVaultManager, VaultPolicy, VaultStatus


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


@pytest.fixture
def manager_no_factory():
    """Create a KeyVaultManager without a factory address."""
    w3 = MagicMock(spec=Web3)
    return KeyVaultManager(w3, "base-mainnet")


def test_create_vault_requires_factory(manager_no_factory):
    """Test vault creation fails without factory address."""
    with pytest.raises(ValueError, match="Factory address not configured"):
        manager_no_factory.create_vault(
            from_address="0x1234567890123456789012345678901234567890",
        )


def test_vault_policy_dataclass():
    """Test VaultPolicy dataclass construction."""
    policy = VaultPolicy(
        max_per_tx=Web3.to_wei(0.1, "ether"),
        max_hourly=Web3.to_wei(0.5, "ether"),
        max_daily=Web3.to_wei(1.0, "ether"),
        emergency_threshold=Web3.to_wei(5.0, "ether"),
        frozen=False,
    )
    assert policy.max_per_tx == Web3.to_wei(0.1, "ether")
    assert not policy.frozen


def test_vault_status_dataclass():
    """Test VaultStatus dataclass construction."""
    status = VaultStatus(
        address="0x1234",
        owner="0x5678",
        balance_wei=Web3.to_wei(1.5, "ether"),
        balance_eth=1.5,
        remaining_hourly_wei=Web3.to_wei(0.3, "ether"),
        remaining_daily_wei=Web3.to_wei(0.8, "ether"),
        policy=VaultPolicy(
            max_per_tx=0,
            max_hourly=0,
            max_daily=0,
            emergency_threshold=0,
            frozen=False,
        ),
    )
    assert status.balance_eth == 1.5
    assert status.address == "0x1234"


def test_freeze_requires_no_factory(manager):
    """Test freeze only needs vault address, not factory."""
    # This should build a transaction (mock will handle it)
    result = manager.freeze(
        vault_address="0x1234567890123456789012345678901234567890",
        from_address="0x1234567890123456789012345678901234567890",
    )
    assert "unsigned_tx" in result
    assert result["description"] == "Emergency freeze KeyVault"


def test_unfreeze_returns_unsigned_tx(manager):
    """Test unfreeze returns an unsigned transaction."""
    result = manager.unfreeze(
        vault_address="0x1234567890123456789012345678901234567890",
        from_address="0x1234567890123456789012345678901234567890",
    )
    assert "unsigned_tx" in result
    assert "Unfreeze" in result["description"]


def test_emergency_withdraw_returns_unsigned_tx(manager):
    """Test emergency withdraw returns an unsigned transaction."""
    result = manager.emergency_withdraw(
        vault_address="0x1234567890123456789012345678901234567890",
        from_address="0x1234567890123456789012345678901234567890",
    )
    assert "unsigned_tx" in result
    assert "Emergency" in result["description"]


def test_allow_contract_returns_unsigned_tx(manager):
    """Test allow contract returns an unsigned transaction."""
    result = manager.allow_contract(
        vault_address="0x1234567890123456789012345678901234567890",
        from_address="0x1234567890123456789012345678901234567890",
        target="0xABCDEF0123456789012345678901234567890123",
    )
    assert "unsigned_tx" in result


def test_execute_returns_unsigned_tx(manager):
    """Test execute returns an unsigned transaction with description."""
    result = manager.execute(
        vault_address="0x1234567890123456789012345678901234567890",
        from_address="0x1234567890123456789012345678901234567890",
        to="0xABCDEF0123456789012345678901234567890123",
        value="0.01",
    )
    assert "unsigned_tx" in result
    assert "Execute via KeyVault" in result["description"]


def test_explorer_link_base():
    """Test explorer link generation for Base."""
    w3 = MagicMock(spec=Web3)
    mgr = KeyVaultManager(w3, "base-mainnet")
    link = mgr._explorer_link("0xabc123")
    assert "basescan.org" in link


def test_explorer_link_unknown_network():
    """Test explorer link for unknown network returns raw hash."""
    w3 = MagicMock(spec=Web3)
    mgr = KeyVaultManager(w3, "unknown-network")
    link = mgr._explorer_link("0xabc123")
    assert link == "0xabc123"
