# app/tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_ohlc_parser.py

from __future__ import annotations

from types import MappingProxyType

import pytest

from src.market_data.acquisition.adapters.dzengi.models import (
    DzengiWebSocketOhlcEvent,
)
from src.market_data.acquisition.adapters.dzengi.parser import (
    parse_dzengi_websocket_ohlc,
)
from src.market_data.acquisition.exceptions import (
    CandleWebSocketParseError,
)
from src.market_data.acquisition.validation.schema import (
    ValidatedWebSocketOhlcDocument,
)


def _validated_document(
    **payload_overrides: object,
) -> ValidatedWebSocketOhlcDocument:
    payload: dict[str, object] = {
        "symbol": "BTC/USD_LEVERAGE",
        "interval": "1m",
        "type": "classic",
        "t": 1784224740000,
        "o": 63992.0,
        "h": 64032.55,
        "l": 63984.0,
        "c": 64032.55,
    }
    payload.update(payload_overrides)

    return ValidatedWebSocketOhlcDocument(
        payload=MappingProxyType(payload),
        status="OK",
        destination="ohlc.event",
        correlation_id=None,
    )


def test_parse_websocket_ohlc_returns_transport_model() -> None:
    result = parse_dzengi_websocket_ohlc(
        _validated_document()
    )

    assert result == DzengiWebSocketOhlcEvent(
        symbol="BTC/USD_LEVERAGE",
        interval="1m",
        candle_type="classic",
        open_time=1784224740000,
        open_price=63992.0,
        high_price=64032.55,
        low_price=63984.0,
        close_price=64032.55,
    )


def test_parse_websocket_ohlc_preserves_heikin_ashi_type() -> None:
    result = parse_dzengi_websocket_ohlc(
        _validated_document(type="heikin-ashi")
    )

    assert result.candle_type == "heikin-ashi"


def test_parse_websocket_ohlc_preserves_raw_numeric_types() -> None:
    result = parse_dzengi_websocket_ohlc(
        _validated_document(
            o="63992.00",
            h=64033,
            l=63984.0,
            c="64032.55",
        )
    )

    assert result.open_price == "63992.00"
    assert result.high_price == 64033
    assert result.low_price == 63984.0
    assert result.close_price == "64032.55"


@pytest.mark.parametrize(
    ("field_name", "value"),
    [
        ("symbol", None),
        ("symbol", 123),
        ("interval", None),
        ("interval", []),
        ("type", None),
        ("type", True),
    ],
)
def test_parse_websocket_ohlc_rejects_non_string_fields(
    field_name: str,
    value: object,
) -> None:
    with pytest.raises(
        CandleWebSocketParseError,
        match=rf"\$\.payload\.{field_name} должен быть строкой",
    ):
        parse_dzengi_websocket_ohlc(
            _validated_document(**{field_name: value})
        )


@pytest.mark.parametrize(
    "value",
    [
        None,
        True,
        1784224740000.0,
        "1784224740000",
        [],
    ],
)
def test_parse_websocket_ohlc_rejects_invalid_open_time(
    value: object,
) -> None:
    with pytest.raises(
        CandleWebSocketParseError,
        match=r"\$\.payload\.t должен быть целым числом",
    ):
        parse_dzengi_websocket_ohlc(
            _validated_document(t=value)
        )


@pytest.mark.parametrize(
    "field_name",
    [
        "o",
        "h",
        "l",
        "c",
    ],
)
@pytest.mark.parametrize(
    "value",
    [
        None,
        True,
        [],
        {},
        object(),
    ],
)
def test_parse_websocket_ohlc_rejects_invalid_raw_numeric(
    field_name: str,
    value: object,
) -> None:
    with pytest.raises(
        CandleWebSocketParseError,
        match=rf"\$\.payload\.{field_name} должен быть строкой или числом",
    ):
        parse_dzengi_websocket_ohlc(
            _validated_document(**{field_name: value})
        )


def test_parse_websocket_ohlc_does_not_validate_subject_values() -> None:
    result = parse_dzengi_websocket_ohlc(
        _validated_document(
            symbol="",
            interval="unsupported",
            type="unknown",
            t=-1,
            o="NaN",
            h=-10,
            l=100,
            c=0,
        )
    )

    assert result.symbol == ""
    assert result.interval == "unsupported"
    assert result.candle_type == "unknown"
    assert result.open_time == -1
    assert result.open_price == "NaN"
    assert result.high_price == -10
    assert result.low_price == 100
    assert result.close_price == 0


def test_parse_websocket_ohlc_ignores_envelope_metadata() -> None:
    document = ValidatedWebSocketOhlcDocument(
        payload=_validated_document().payload,
        status=123,
        destination=None,
        correlation_id={"unexpected": "value"},
    )

    result = parse_dzengi_websocket_ohlc(document)

    assert result.symbol == "BTC/USD_LEVERAGE"
    assert result.interval == "1m"