import ccxt
import pandas as pd
import logging
from typing import Dict, List, Optional
from app.data_layer.binance_client import binance_client

logger = logging.getLogger(__name__)

# Supported timeframes mapped to CCXT format
TIMEFRAMES = {
    "15m": "15m",
    "1h": "1h",
    "4h": "4h",
    "1d": "1d",
}


def fetch_ohlcv(
    symbol: str, timeframe: str = "1h", limit: int = 200
) -> pd.DataFrame:
    """
    Fetch OHLCV candlestick data from Binance and return as a DataFrame.
    Columns: open, high, low, close, volume (datetime index).
    """
    exchange = binance_client.get_readonly_exchange()
    try:
        ohlcv = exchange.fetch_ohlcv(symbol, timeframe=timeframe, limit=limit)
        df = pd.DataFrame(
            ohlcv, columns=["timestamp", "open", "high", "low", "close", "volume"]
        )
        df["timestamp"] = pd.to_datetime(df["timestamp"], unit="ms")
        df.set_index("timestamp", inplace=True)
        return df
    except ccxt.BaseError as e:
        logger.error(f"Error fetching OHLCV for {symbol} {timeframe}: {e}")
        raise


def fetch_multi_timeframe(
    symbol: str, timeframes: List[str] = None, limit: int = 200
) -> Dict[str, pd.DataFrame]:
    """
    Fetch OHLCV data for multiple timeframes.
    Returns a dict keyed by timeframe string.
    """
    if timeframes is None:
        timeframes = ["15m", "1h"]

    result = {}
    for tf in timeframes:
        result[tf] = fetch_ohlcv(symbol, timeframe=tf, limit=limit)
    return result


def get_current_price(symbol: str) -> Optional[float]:
    """Fetch the latest ask price for a symbol."""
    exchange = binance_client.get_readonly_exchange()
    try:
        ticker = exchange.fetch_ticker(symbol)
        return float(ticker["last"])
    except ccxt.BaseError as e:
        logger.error(f"Error fetching current price for {symbol}: {e}")
        return None


def get_supported_pairs() -> List[str]:
    """Return a list of active USDT spot trading pairs."""
    exchange = binance_client.get_readonly_exchange()
    markets = exchange.load_markets()
    pairs = [
        symbol
        for symbol, market in markets.items()
        if market.get("quote") == "USDT" and market.get("active") and market.get("spot")
    ]
    return sorted(pairs)
