"""Tests for Pydantic models — camelCase alias parsing."""

from boxtime.models import (
    Asset,
    Balance,
    BlockHeader,
    CointimeDataPoint,
    DataInput,
    EmissionInfo,
    ErgoBox,
    PowSolutions,
    PriceHistory,
    PricePoint,
    SpendingProof,
    Transaction,
)
from tests.conftest import (
    BLOCK_HEADER_JSON,
    EMISSION_JSON,
    ERGO_BOX_JSON,
    TRANSACTION_JSON,
)


# ------------------------------------------------------------------
# Node models
# ------------------------------------------------------------------


def test_emission_info():
    m = EmissionInfo(**EMISSION_JSON)
    assert m.miner_reward == 67500000000
    assert m.total_coins_issued == 50_000_000_000_000_000
    assert m.total_remain_coins == 47_284_800_000_000_000
    assert m.reemitted == 0


def test_block_header():
    m = BlockHeader(**BLOCK_HEADER_JSON)
    assert m.id == "header123"
    assert m.height == 1000
    assert m.timestamp == 1700000000000
    assert m.ad_proofs_root == "abc"
    assert m.state_root == "def"
    assert m.transactions_root == "ghi"
    assert m.n_bits == 117440512
    assert m.extension_hash == "jkl"
    assert m.parent_id == "parent123"
    assert m.votes == "000000"
    assert isinstance(m.pow_solutions, PowSolutions)
    assert m.pow_solutions.pk == "pk123"


def test_ergo_box():
    m = ErgoBox(**ERGO_BOX_JSON)
    assert m.box_id == "box123"
    assert m.value == 1_000_000_000
    assert m.ergo_tree == "0008cd..."
    assert m.creation_height == 900
    assert m.inclusion_height == 950
    assert m.global_index == 42
    assert m.assets == []
    assert m.additional_registers == {}


def test_ergo_box_minimal():
    """ErgoBox with only required fields (output, no indexer metadata)."""
    m = ErgoBox(
        value=100,
        ergoTree="0008cd...",
        creationHeight=500,
    )
    assert m.value == 100
    assert m.box_id is None
    assert m.inclusion_height is None


def test_transaction():
    m = Transaction(**TRANSACTION_JSON)
    assert m.id == "tx123"
    assert m.inclusion_height == 1000
    assert m.num_confirmations == 100
    assert m.block_id == "block123"
    assert m.timestamp == 1700000000000
    assert m.global_index == 5000
    assert m.size == 300
    assert len(m.inputs) == 1
    assert len(m.outputs) == 1
    assert m.inputs[0].value == 500_000_000
    assert m.inputs[0].inclusion_height == 900
    assert m.data_inputs == []


def test_asset():
    m = Asset(tokenId="tok123", amount=500)
    assert m.token_id == "tok123"
    assert m.amount == 500


def test_data_input():
    m = DataInput(boxId="box456")
    assert m.box_id == "box456"


def test_spending_proof():
    m = SpendingProof(proofBytes="deadbeef", extension={"k": "v"})
    assert m.proof_bytes == "deadbeef"
    assert m.extension == {"k": "v"}


def test_pow_solutions():
    m = PowSolutions(pk="pk1", w="w1", n="n1", d=0.0)
    assert m.pk == "pk1"
    assert m.d == 0.0


def test_balance():
    m = Balance(nanoErgs=5_000_000_000, tokens=[{"tokenId": "t1", "amount": 10}])
    assert m.nano_ergs == 5_000_000_000
    assert len(m.tokens) == 1
    assert m.tokens[0].token_id == "t1"


def test_balance_empty_tokens():
    m = Balance(nanoErgs=1000, tokens=[])
    assert m.nano_ergs == 1000
    assert m.tokens == []


# ------------------------------------------------------------------
# Price models
# ------------------------------------------------------------------


def test_price_point():
    m = PricePoint(timestamp=1700000000000, price=1.5)
    assert m.timestamp == 1700000000000
    assert m.price == 1.5


def test_price_history():
    m = PriceHistory(
        coin_id="ergo",
        vs_currency="usd",
        prices=[PricePoint(timestamp=1700000000000, price=1.5)],
    )
    assert m.coin_id == "ergo"
    assert m.vs_currency == "usd"
    assert len(m.prices) == 1


# ------------------------------------------------------------------
# Cointime models
# ------------------------------------------------------------------


def test_cointime_data_point():
    m = CointimeDataPoint(
        height=1000, timestamp=1700000000000, value=50_000, price=1.5
    )
    assert m.height == 1000
    assert m.timestamp == 1700000000000
    assert m.value == 50_000
    assert m.price == 1.5
