# app/tests/unit/integrations/exchange/test_market_cache.py

from __future__ import annotations

from datetime import datetime, timezone
from decimal import Decimal
from typing import Iterator

import pytest

from src.integrations.exchange.market_cache import MarketPriceCache
from src.market_data.acquisition.models.quote import Quote
from src.storage.quote_store import InMemoryQuoteStore, QuoteStoreProtocol


def _quote(symbol: str = "BTC/USD_LEVERAGE") -> Quote:
    return Quote(
        symbol=symbol,
        last_price=Decimal("100"),
        bid_price=Decimal("99"),
        ask_price=Decimal("101"),
        exchange_timestamp=None,
        received_at=datetime.now(timezone.utc),
        source="test",
    )


@pytest.fixture(autouse=True)
def reset_market_price_cache() -> Iterator[None]:
    original_store = MarketPriceCache._store
    MarketPriceCache._store = InMemoryQuoteStore()
    yield
    MarketPriceCache._store = original_store


def test_market_price_cache_uses_quote_store_protocol() -> None:
    assert isinstance(MarketPriceCache._store, QuoteStoreProtocol)


def test_set_and_get_quote_preserve_identity() -> None:
    quote = _quote()
    MarketPriceCache.set_quote(quote, runtime_key="auto")
    assert MarketPriceCache.get_quote(quote.symbol, runtime_key="auto") is quote


def test_symbol_and_runtime_key_are_normalized() -> None:
    quote = _quote("BTC/USD_LEVERAGE")
    MarketPriceCache.set_quote(quote, runtime_key="  AUTO  ")
    assert MarketPriceCache.get_quote(" btc/usd_leverage ", runtime_key="auto") is quote


def test_runtime_keys_are_isolated() -> None:
    auto = _quote()
    debug = Quote(
        symbol=auto.symbol, last_price=Decimal("200"), bid_price=Decimal("199"),
        ask_price=Decimal("201"), exchange_timestamp=None,
        received_at=datetime.now(timezone.utc), source="debug",
    )
    MarketPriceCache.set_quote(auto, runtime_key="auto")
    MarketPriceCache.set_quote(debug, runtime_key="debug_auto")
    assert MarketPriceCache.get_quote(auto.symbol, runtime_key="auto") is auto
    assert MarketPriceCache.get_quote(auto.symbol, runtime_key="debug_auto") is debug


def test_clear_targeted_and_all() -> None:
    btc = _quote("BTC/USD_LEVERAGE")
    eth = _quote("ETH/USD_LEVERAGE")
    MarketPriceCache.set_quote(btc, runtime_key="auto")
    MarketPriceCache.set_quote(eth, runtime_key="auto")
    MarketPriceCache.clear(btc.symbol, runtime_key="auto")
    assert MarketPriceCache.get_quote(btc.symbol, runtime_key="auto") is None
    assert MarketPriceCache.get_quote(eth.symbol, runtime_key="auto") is eth
    MarketPriceCache.clear()
    assert MarketPriceCache.get_quote(eth.symbol, runtime_key="auto") is None
