"""
Unit tests for Binance raw → domain event parsing.
"""
import pytest
from app.providers.binance import BinanceProvider
from app.domain.events import EventType


@pytest.fixture
def provider():
    return BinanceProvider()


# ── Trade parsing ──────────────────────────────────────────────────────

BINANCE_TRADE_RAW = {
    "e": "trade",
    "E": 1672515782136,
    "s": "BTCUSDT",
    "t": 123456789,
    "p": "42500.50",
    "q": "0.015",
    "T": 1672515782135,
    "m": True,
}


def test_parse_trade_basic(provider):
    event = provider._parse(BINANCE_TRADE_RAW)
    assert event is not None
    assert event.event_type == EventType.TRADE
    assert event.symbol == "BTCUSDT"
    assert event.price == 42500.50
    assert event.size == 0.015
    assert event.side == "sell"  # m=True → seller is maker → trade is sell
    assert event.trade_id == "123456789"
    assert event.provider == "binance"


def test_parse_trade_ts_exchange(provider):
    event = provider._parse(BINANCE_TRADE_RAW)
    assert event.ts_exchange is not None
    # 1672515782135 ms → 2022-12-31 or 2023-01-01 (depending on TZ)
    assert event.ts_exchange.year >= 2022


def test_parse_trade_buy_side(provider):
    raw = {**BINANCE_TRADE_RAW, "m": False}
    event = provider._parse(raw)
    assert event.side == "buy"


# ── BookTicker (Quote) parsing ─────────────────────────────────────────

BINANCE_BOOKTICKER_RAW = {
    "u": 400900217,
    "s": "ETHUSDT",
    "b": "2150.25000000",
    "B": "31.21000000",
    "a": "2150.50000000",
    "A": "40.66000000",
}


def test_parse_bookticker(provider):
    event = provider._parse(BINANCE_BOOKTICKER_RAW)
    assert event is not None
    assert event.event_type == EventType.QUOTE
    assert event.symbol == "ETHUSDT"
    assert event.bid == 2150.25
    assert event.ask == 2150.50
    assert event.bid_size == 31.21
    assert event.ask_size == 40.66
    assert event.provider == "binance"


# ── Edge cases ─────────────────────────────────────────────────────────

def test_parse_unknown_event(provider):
    raw = {"e": "aggTrade", "s": "BTCUSDT", "p": "100"}
    event = provider._parse(raw)
    assert event is None


def test_parse_subscription_confirmation(provider):
    raw = {"result": None, "id": 1}
    # This is handled in stream(), not _parse(), so _parse should return None
    event = provider._parse(raw)
    assert event is None


def test_parse_empty_values(provider):
    raw = {"e": "trade", "s": "", "p": "0", "q": "0", "T": None, "m": True, "t": ""}
    event = provider._parse(raw)
    assert event is not None
    assert event.price == 0.0
    assert event.symbol == ""
