"""Tests for social-value wallet — security, validation, fee estimation."""

import pytest

from social_value.config import SocialValueConfig
from social_value.types import SecretStr
from social_value.wallet import SocialValue, SocialValueError


@pytest.fixture
def liquid_wallet():
    config = SocialValueConfig(breez_api_key=SecretStr("test-key"), backend="liquid")
    return SocialValue(config=config, mnemonic=SecretStr("test mnemonic words"))


@pytest.fixture
def spark_wallet():
    config = SocialValueConfig(breez_api_key=SecretStr("test-key"), backend="spark")
    return SocialValue(config=config, mnemonic=SecretStr("test mnemonic words"))


# ── Secret redaction ─────────────────────────────────────────


def test_repr_redacts_mnemonic(liquid_wallet):
    r = repr(liquid_wallet)
    assert "test mnemonic" not in r
    assert "***" in r


def test_repr_redacts_after_format(liquid_wallet):
    s = f"Wallet: {liquid_wallet!r}"
    assert "test mnemonic" not in s


# ── Backend selection ────────────────────────────────────────


def test_liquid_backend_name(liquid_wallet):
    assert liquid_wallet.backend_name == "liquid"


def test_spark_backend_name(spark_wallet):
    assert spark_wallet.backend_name == "spark"


# ── Connection guards ────────────────────────────────────────


def test_wallet_not_connected(liquid_wallet):
    assert liquid_wallet.connected is False


def test_wallet_requires_connection(liquid_wallet):
    with pytest.raises(SocialValueError, match="Not connected"):
        liquid_wallet.get_state()


def test_deposit_requires_connection(liquid_wallet):
    with pytest.raises(SocialValueError, match="Not connected"):
        liquid_wallet.deposit(1000)


def test_transfer_requires_connection(liquid_wallet):
    with pytest.raises(SocialValueError, match="Not connected"):
        liquid_wallet.transfer("dest", 100)


# ── Input validation ─────────────────────────────────────────


def test_estimate_rejects_zero_amount(liquid_wallet):
    with pytest.raises(ValueError, match="positive"):
        liquid_wallet.estimate_fees("deposit", 0)


def test_estimate_rejects_negative_amount(liquid_wallet):
    with pytest.raises(ValueError, match="positive"):
        liquid_wallet.estimate_fees("deposit", -100)


def test_estimate_rejects_non_int(liquid_wallet):
    with pytest.raises(TypeError, match="integer"):
        liquid_wallet.estimate_fees("deposit", 100.5)


def test_estimate_unknown_action(liquid_wallet):
    with pytest.raises(ValueError, match="Unknown action"):
        liquid_wallet.estimate_fees("unknown", 1000)


def test_list_payments_rejects_zero_limit(liquid_wallet):
    # list_payments validates even without connection for limit/offset
    # but it also requires connection — test the validation message
    with pytest.raises(SocialValueError, match="Not connected"):
        liquid_wallet.list_payments(limit=0)


# ── Liquid fee estimates ─────────────────────────────────────


def test_liquid_estimate_deposit(liquid_wallet):
    est = liquid_wallet.estimate_fees("deposit", 5000)
    assert est.action == "deposit"
    assert est.amount_sat == 5000
    assert est.fee_sat > 0
    assert est.fee_pct > 0


def test_liquid_estimate_internal(liquid_wallet):
    est = liquid_wallet.estimate_fees("transfer_internal", 100)
    assert est.fee_sat == 1


def test_liquid_estimate_lightning(liquid_wallet):
    est = liquid_wallet.estimate_fees("transfer_lightning", 5000)
    assert est.fee_sat > 0
    assert est.fee_sat > liquid_wallet.estimate_fees("transfer_internal", 5000).fee_sat


def test_liquid_estimate_withdraw(liquid_wallet):
    est = liquid_wallet.estimate_fees("withdraw", 5000)
    assert est.fee_sat > 0


# ── Spark fee estimates ──────────────────────────────────────


def test_spark_estimate_deposit(spark_wallet):
    est = spark_wallet.estimate_fees("deposit", 5000)
    assert est.fee_sat > 0


def test_spark_estimate_internal(spark_wallet):
    est = spark_wallet.estimate_fees("transfer_internal", 100)
    assert est.fee_sat == 0


def test_spark_cheaper_than_liquid_internal(liquid_wallet, spark_wallet):
    liquid_fee = liquid_wallet.estimate_fees("transfer_internal", 100).fee_sat
    spark_fee = spark_wallet.estimate_fees("transfer_internal", 100).fee_sat
    assert spark_fee <= liquid_fee


def test_spark_cheaper_deposit(liquid_wallet, spark_wallet):
    liquid_fee = liquid_wallet.estimate_fees("deposit", 5000).fee_sat
    spark_fee = spark_wallet.estimate_fees("deposit", 5000).fee_sat
    assert spark_fee < liquid_fee


# ── Amortization proof ───────────────────────────────────────


def test_amortization_advantage(liquid_wallet):
    """Internal transfers are always cheaper than Lightning transfers."""
    n_transfers = 10
    amount_per = 100

    lightning_total = sum(
        liquid_wallet.estimate_fees("transfer_lightning", amount_per).fee_sat
        for _ in range(n_transfers)
    )
    internal_total = sum(
        liquid_wallet.estimate_fees("transfer_internal", amount_per).fee_sat
        for _ in range(n_transfers)
    )

    assert internal_total < lightning_total
