from decimal import Decimal

from binance_quant.models import (
    AccountSnapshot,
    Balance,
    Candle,
    OrderSide,
    Signal,
    SignalType,
    SymbolMetadata,
)


def test_signal_uses_uppercase_side_and_symbol():
    signal = Signal(
        symbol="btcusdt",
        signal_type=SignalType.BUY,
        side=OrderSide.BUY,
        reason="fast SMA crossed above slow SMA",
    )

    assert signal.symbol == "BTCUSDT"
    assert signal.side is OrderSide.BUY


def test_symbol_metadata_extracts_assets_from_symbol():
    metadata = SymbolMetadata(
        symbol="BTCUSDT",
        base_asset="BTC",
        quote_asset="USDT",
        min_notional=Decimal("5"),
        min_qty=Decimal("0.00001"),
        step_size=Decimal("0.00001"),
    )

    assert metadata.base_asset == "BTC"
    assert metadata.quote_asset == "USDT"


def test_candle_reports_close_price_as_decimal():
    candle = Candle(
        symbol="BTCUSDT",
        open_time=1,
        close_time=2,
        open=Decimal("10"),
        high=Decimal("12"),
        low=Decimal("9"),
        close=Decimal("11"),
        volume=Decimal("1.5"),
    )

    assert candle.close == Decimal("11")


def test_candle_defaults_optional_binance_kline_fields_to_zero():
    candle = Candle(
        symbol="BTCUSDT",
        open_time=1,
        close_time=2,
        open=Decimal("10"),
        high=Decimal("12"),
        low=Decimal("9"),
        close=Decimal("11"),
        volume=Decimal("1.5"),
    )

    assert candle.quote_volume == Decimal("0")
    assert candle.trade_count == 0
    assert candle.taker_buy_base_volume == Decimal("0")
    assert candle.taker_buy_quote_volume == Decimal("0")


def test_candle_accepts_optional_binance_kline_fields():
    candle = Candle(
        symbol="btcusdt",
        open_time=1,
        close_time=2,
        open=Decimal("10"),
        high=Decimal("12"),
        low=Decimal("9"),
        close=Decimal("11"),
        volume=Decimal("1.5"),
        quote_volume=Decimal("16.5"),
        trade_count=7,
        taker_buy_base_volume=Decimal("0.8"),
        taker_buy_quote_volume=Decimal("8.8"),
    )

    assert candle.symbol == "BTCUSDT"
    assert candle.quote_volume == Decimal("16.5")
    assert candle.trade_count == 7
    assert candle.taker_buy_base_volume == Decimal("0.8")
    assert candle.taker_buy_quote_volume == Decimal("8.8")


def test_account_snapshot_normalizes_balance_keys():
    snapshot = AccountSnapshot({"usdt": Balance("usdt", Decimal("7"))})

    assert snapshot.free("USDT") == Decimal("7")
    assert snapshot.free("missing") == Decimal("0")
