"""Market Data Feed Manager and Aggregator."""
from __future__ import annotations

import time
from decimal import Decimal
from typing import Any, Optional

from backend.app.audit.logger import audit_logger
from backend.app.config.settings import TradingMode, settings
from backend.app.market_data.bybit_client import BybitV5Client
from backend.app.market_data.mock_client import MockBybitClient
from backend.app.monitoring.health import health_service
from backend.app.schemas.market import Candle, OrderBook, Ticker
from backend.app.schemas.risk import InstrumentFilters


class FeedManager:
    """Manages active market data feed with automatic fallbacks and freshness monitoring."""

    def __init__(self, mode: Optional[TradingMode] = None) -> None:
        self.mode = mode or settings.TRADING_MODE
        self.mock_client = MockBybitClient()
        self.bybit_client = BybitV5Client(mode=self.mode)
        self._candle_cache: dict[str, list[Candle]] = {}
        self._ticker_cache: dict[str, Ticker] = {}

    def get_client(self) -> Any:
        if self.mode in [TradingMode.BYBIT_DEMO, TradingMode.LIVE]:
            return self.bybit_client
        return self.mock_client

    def fetch_klines(self, symbol: str, interval: str = "15m", limit: int = 150) -> list[Candle]:
        try:
            client = self.get_client()
            candles = client.get_klines(symbol=symbol, interval=interval, limit=limit)
            if candles:
                self._candle_cache[f"{symbol}_{interval}"] = candles
                health_service.record_market_tick()
                return candles
        except Exception as e:
            audit_logger.warning("Primary market feed error for %s: %s. Using fallback.", symbol, str(e))
        # Fallback to mock data for resilience
        fallback_candles = self.mock_client.get_klines(symbol=symbol, interval=interval, limit=limit)
        self._candle_cache[f"{symbol}_{interval}"] = fallback_candles
        health_service.record_market_tick()
        return fallback_candles

    def fetch_ticker(self, symbol: str) -> Ticker:
        try:
            client = self.get_client()
            ticker = client.get_ticker(symbol)
            self._ticker_cache[symbol] = ticker
            health_service.record_market_tick()
            return ticker
        except Exception as e:
            audit_logger.warning("Ticker fetch error for %s: %s. Using fallback.", symbol, str(e))
        fallback_ticker = self.mock_client.get_ticker(symbol)
        self._ticker_cache[symbol] = fallback_ticker
        health_service.record_market_tick()
        return fallback_ticker

    def fetch_orderbook(self, symbol: str, limit: int = 50) -> OrderBook:
        try:
            client = self.get_client()
            return client.get_orderbook(symbol, limit)
        except Exception:
            return self.mock_client.get_orderbook(symbol, limit)

    def fetch_instrument_filters(self, symbol: str) -> InstrumentFilters:
        try:
            client = self.get_client()
            return client.get_instrument_filters(symbol)
        except Exception:
            return self.mock_client.get_instrument_filters(symbol)


feed_manager = FeedManager()
