# app/tests/unit/market_data/acquisition/validation/test_candle_schema.py

from __future__ import annotations

from types import MappingProxyType

import pytest

from src.market_data.acquisition.exceptions import CandleSchemaError
from src.market_data.acquisition.validation.schema import (
    validate_candles_schema,
)


_VALID_ARRAY_ITEM = [1000, "100", "110", "90", "105", "12.5"]
_VALID_OBJECT_ITEM = {
    "openTime": 1000,
    "open": "100",
    "high": "110",
    "low": "90",
    "close": "105",
    "volume": "12.5",
}


@pytest.mark.parametrize(
    "document",
    [
        [_VALID_ARRAY_ITEM],
        {"klines": [_VALID_ARRAY_ITEM]},
        {"candles": [_VALID_ARRAY_ITEM]},
        {"data": [_VALID_ARRAY_ITEM]},
        {"result": [_VALID_ARRAY_ITEM]},
        {"payload": [_VALID_ARRAY_ITEM]},
        {"payload": {"klines": [_VALID_ARRAY_ITEM]}},
        {"payload": {"candles": [_VALID_ARRAY_ITEM]}},
        {"payload": {"data": [_VALID_ARRAY_ITEM]}},
    ],
)
def test_validate_candles_schema_accepts_supported_envelopes(
    document: object,
) -> None:
    result = validate_candles_schema(document)

    assert len(result.items) == 1
    assert result.items[0] == tuple(_VALID_ARRAY_ITEM)


def test_validate_candles_schema_accepts_object_item() -> None:
    result = validate_candles_schema([_VALID_OBJECT_ITEM])

    assert len(result.items) == 1
    assert isinstance(result.items[0], MappingProxyType)
    assert dict(result.items[0]) == _VALID_OBJECT_ITEM


def test_validate_candles_schema_accepts_empty_list() -> None:
    result = validate_candles_schema([])

    assert result.items == ()


@pytest.mark.parametrize(
    "document",
    [
        None,
        "invalid",
        123,
        {"unknown": []},
        {"payload": {"unknown": []}},
    ],
)
def test_validate_candles_schema_rejects_unknown_document(
    document: object,
) -> None:
    with pytest.raises(CandleSchemaError):
        validate_candles_schema(document)


@pytest.mark.parametrize(
    "document",
    [
        {"klines": {}},
        {"payload": {"klines": {}}},
    ],
)
def test_validate_candles_schema_rejects_non_list_container(
    document: object,
) -> None:
    with pytest.raises(CandleSchemaError, match="JSON-массивом"):
        validate_candles_schema(document)


@pytest.mark.parametrize(
    "item",
    [
        "invalid",
        123,
        None,
        True,
    ],
)
def test_validate_candles_schema_rejects_invalid_item(
    item: object,
) -> None:
    with pytest.raises(
        CandleSchemaError,
        match="JSON-объектом или JSON-массивом",
    ):
        validate_candles_schema([item])


def test_validate_candles_schema_rejects_short_array() -> None:
    with pytest.raises(CandleSchemaError, match="минимум 6"):
        validate_candles_schema([[1000, "100", "110"]])


def test_validate_candles_schema_rejects_non_string_object_key() -> None:
    with pytest.raises(CandleSchemaError, match="нестроковый ключ"):
        validate_candles_schema([{1: "invalid"}])
