"""US-006 tests: Solana contract boundary for stake, payment, and settlement."""

from meshnet_contracts import LocalSolanaContracts


def test_node_stake_is_reflected_in_registry():
    "A node can submit stake and read the updated registry balance.\n\nTags: billing, contracts, settlement"

    contracts = LocalSolanaContracts()

    receipt = contracts.registry.submit_stake("node-wallet-a", 500)

    assert receipt["cluster"] == "local-test-validator"
    assert contracts.registry.get_wallet("node-wallet-a").stake_balance == 500
    assert contracts.registry.has_minimum_stake("node-wallet-a", minimum_stake=100)


def test_client_can_fund_api_key_with_testnet_sol():
    "A client can fund an API key account and read the available balance.\n\nTags: billing, contracts, settlement"

    contracts = LocalSolanaContracts()

    receipt = contracts.payment.fund_api_key("api-key-a", lamports=2_000)

    assert receipt["cluster"] == "local-test-validator"
    assert contracts.payment.get_balance("api-key-a").lamports == 3_000


def test_epoch_settlement_debits_clients_and_rewards_nodes_and_validator():
    "Settlement distributes native token rewards according to recorded work.\n\nTags: billing, contracts, settlement"

    contracts = LocalSolanaContracts(
        cost_per_layer_token_lamport=2,
        probationary_job_count=0,
    )
    contracts.payment.fund_api_key("api-key-a", lamports=1_000)
    contracts.payment.record_attribution(
        session_id="session-a",
        api_key="api-key-a",
        node_wallet="node-wallet-a",
        layer_start=0,
        layer_end=15,
        tokens=10,
    )
    contracts.payment.record_attribution(
        session_id="session-a",
        api_key="api-key-a",
        node_wallet="node-wallet-b",
        layer_start=16,
        layer_end=31,
        tokens=10,
        speed_score=2.0,
    )

    result = contracts.settlement.settle_epoch(
        epoch=1,
        validator_wallet="validator-wallet",
        validator_reward_share_bps=1_000,
    )

    assert result.client_debits == {"api-key-a": 640}
    assert result.node_rewards == {"node-wallet-a": 96, "node-wallet-b": 192}
    assert result.validator_rewards == {"validator-wallet": 32}
    assert contracts.payment.get_balance("api-key-a").lamports == 1_360
    assert contracts.settlement.get_token_balance("node-wallet-a") == 96
    assert contracts.settlement.get_token_balance("node-wallet-b") == 192
    assert contracts.settlement.get_token_balance("validator-wallet") == 32


def test_failed_settlement_does_not_advance_probation_or_settle_attribution():
    "Settlement state is unchanged when caller balance validation fails.\n\nTags: billing, contracts, settlement"

    contracts = LocalSolanaContracts(starting_credit_lamports=0, probationary_job_count=1)
    contracts.payment.record_attribution(
        session_id="session-a",
        api_key="api-key-a",
        node_wallet="node-wallet-a",
        layer_start=0,
        layer_end=0,
        tokens=1,
    )

    try:
        contracts.settlement.settle_epoch(epoch=1)
        raise AssertionError("Expected insufficient balance")
    except ValueError as exc:
        assert "insufficient SOL balance" in str(exc)

    assert contracts.registry.get_wallet("node-wallet-a").completed_job_count == 0
    assert contracts.payment.list_attributions(include_settled=False)


def test_slash_proof_reduces_stake_increments_strikes_and_warns(capsys):
    "Submitting a slash proof updates registry state and notifies the operator.\n\nTags: billing, contracts, settlement"

    contracts = LocalSolanaContracts()
    contracts.registry.submit_stake("node-wallet-a", 500)

    receipt = contracts.registry.submit_slash_proof(
        wallet_address="node-wallet-a",
        slash_amount=125,
        strike_threshold=2,
        reason="test divergence",
    )

    wallet = contracts.registry.get_wallet("node-wallet-a")
    assert receipt.signature.startswith("local-slash-node-wallet-a")
    assert wallet.stake_balance == 375
    assert wallet.strike_count == 1
    assert wallet.banned is False
    assert "WARNING: node node-wallet-a slashed" in capsys.readouterr().out


def test_probationary_wallet_earns_only_after_required_jobs():
    "A new wallet's first N completed jobs are counted but not rewarded.\n\nTags: billing, contracts, security, settlement, wallet"

    contracts = LocalSolanaContracts(probationary_job_count=2)
    contracts.payment.fund_api_key("api-key-a", lamports=1_000)
    for job_number in range(3):
        contracts.payment.record_attribution(
            session_id=f"session-{job_number}",
            api_key="api-key-a",
            node_wallet="new-wallet",
            layer_start=0,
            layer_end=0,
            tokens=10,
        )

    result = contracts.settlement.settle_epoch(epoch=1)

    assert result.client_debits == {"api-key-a": 30}
    assert result.node_rewards == {"new-wallet": 10}
    assert contracts.registry.get_wallet("new-wallet").completed_job_count == 3
    assert contracts.registry.probationary_jobs_remaining("new-wallet") == 0
    assert contracts.settlement.get_token_balance("new-wallet") == 10


def test_probationary_wallet_receives_no_rewards_before_threshold():
    "Settlement state verifies a wallet earns zero during probation.\n\nTags: billing, contracts, security, settlement, wallet"

    contracts = LocalSolanaContracts(probationary_job_count=50)
    contracts.payment.fund_api_key("api-key-a", lamports=1_000)
    contracts.payment.record_attribution(
        session_id="session-a",
        api_key="api-key-a",
        node_wallet="new-wallet",
        layer_start=0,
        layer_end=9,
        tokens=1,
    )

    result = contracts.settlement.settle_epoch(epoch=1)

    assert result.node_rewards == {"new-wallet": 0}
    assert contracts.registry.get_wallet("new-wallet").completed_job_count == 1
    assert contracts.registry.probationary_jobs_remaining("new-wallet") == 49
    assert contracts.settlement.get_token_balance("new-wallet") == 0


def test_slash_proof_at_threshold_marks_wallet_banned():
    "Registry marks a wallet banned when strikes reach the configured threshold.\n\nTags: billing, contracts, security, settlement, wallet"

    contracts = LocalSolanaContracts()
    contracts.registry.submit_stake("node-wallet-a", 500)
    contracts.registry.submit_slash_proof(
        wallet_address="node-wallet-a",
        slash_amount=10,
        strike_threshold=2,
    )

    receipt = contracts.registry.submit_slash_proof(
        wallet_address="node-wallet-a",
        slash_amount=10,
        strike_threshold=2,
    )

    assert receipt.banned is True
    wallet = contracts.registry.get_wallet("node-wallet-a")
    assert wallet.strike_count == 2
    assert wallet.banned is True
