"""Price feed provider using CoinGecko API."""
import aiohttp
from typing import Optional
from .base import BaseProvider, OracleData


class PriceProvider(BaseProvider):
    """Crypto price oracle provider using CoinGecko."""

    name = "price"

    COINGECKO_API = "https://api.coingecko.com/api/v3"

    # Map common symbols to CoinGecko IDs
    SYMBOL_MAP = {
        "BTC": "bitcoin",
        "ETH": "ethereum",
        "SOL": "solana",
        "MATIC": "matic-network",
        "AVAX": "avalanche-2",
        "NPY": "nanopy",  # Future listing
    }

    def __init__(self, api_key: Optional[str] = None):
        self.api_key = api_key

    async def fetch(self, key: str, **kwargs) -> OracleData:
        """Fetch price for a trading pair.

        Args:
            key: Trading pair like "ETH/USD" or "BTC/EUR"
            **kwargs: Additional arguments

        Returns:
            OracleData with price
        """
        parts = key.upper().split("/")
        if len(parts) != 2:
            raise ValueError(f"Invalid pair format: {key}. Use 'SYMBOL/CURRENCY' (e.g., 'ETH/USD')")

        symbol, currency = parts
        coin_id = self.SYMBOL_MAP.get(symbol, symbol.lower())
        vs_currency = currency.lower()

        async with aiohttp.ClientSession() as session:
            url = f"{self.COINGECKO_API}/simple/price"
            params = {
                "ids": coin_id,
                "vs_currencies": vs_currency,
                "include_24hr_change": "true",
                "include_last_updated_at": "true",
            }

            async with session.get(url, params=params) as resp:
                if resp.status != 200:
                    raise Exception(f"CoinGecko API error: {resp.status}")

                data = await resp.json()

                if coin_id not in data:
                    raise ValueError(f"Unknown coin: {symbol}")

                coin_data = data[coin_id]
                price = coin_data.get(vs_currency)
                change_24h = coin_data.get(f"{vs_currency}_24h_change", 0)

                if price is None:
                    raise ValueError(f"Price not available for {key}")

                return self.create_data(
                    key=key,
                    value=price,
                    confidence=0.99,  # High confidence from CoinGecko
                    metadata={
                        "source": "coingecko",
                        "change_24h": change_24h,
                        "currency": currency,
                    },
                )

    async def validate(self, data: OracleData) -> bool:
        """Validate price data."""
        if not isinstance(data.value, (int, float)):
            return False
        if data.value <= 0:
            return False
        return True


class MultiPriceProvider(PriceProvider):
    """Fetch multiple prices in one call."""

    name = "price_multi"

    async def fetch_many(self, pairs: list[str]) -> list[OracleData]:
        """Fetch multiple price pairs efficiently."""
        results = []
        for pair in pairs:
            try:
                data = await self.fetch(pair)
                results.append(data)
            except Exception as e:
                print(f"[Warning] Failed to fetch {pair}: {e}")
        return results
