"""
Token Launch Discovery — DexScreener + GeckoTerminal + GoPlus Security
=======================================================================
Multi-chain real-time token discovery. Add this route to main.py:
    from app.token_discovery import discover_endpoint
    app.include_router(discover_endpoint)
"""

import logging
from datetime import UTC, datetime

import httpx

logger = logging.getLogger(__name__)

MONITORED_CHAINS = {
    "solana": "solana",
    "ethereum": "1",
    "bsc": "56",
    "base": "8453",
    "arbitrum": "42161",
    "polygon": "137",
    "avalanche": "43114",
}


async def fetch_dexscreener_new_pairs(chain: str, limit: int = 20) -> list[dict]:
    """Fetch newest trading pairs from DexScreener."""
    url = "https://api.dexscreener.com/latest/dex/search"
    async with httpx.AsyncClient(timeout=15.0) as client:
        try:
            resp = await client.get(url, params={"q": chain, "limit": limit})
            resp.raise_for_status()
            pairs = resp.json().get("pairs", [])
            now = datetime.now(UTC)
            recent = []
            for pair in pairs:
                created = pair.get("pairCreatedAt")
                if created:
                    age = (now - datetime.fromtimestamp(created / 1000, tz=UTC)).total_seconds() / 3600
                    if age <= 24:
                        recent.append(pair)
            logger.info(f"DexScreener: {len(recent)} recent pairs on {chain}")
            return recent
        except Exception as e:
            logger.error(f"DexScreener {chain}: {e}")
            return []


async def fetch_gecko_new_pools(network: str, limit: int = 20) -> list[dict]:
    """Fetch newest pools from GeckoTerminal."""
    url = f"https://api.geckoterminal.com/api/v2/networks/{network}/new_pools"
    async with httpx.AsyncClient(timeout=15.0) as client:
        try:
            resp = await client.get(url, params={"limit": limit})
            if resp.status_code == 404:
                return []
            resp.raise_for_status()
            return resp.json().get("data", [])
        except Exception as e:
            logger.warning(f"GeckoTerminal {network}: {e}")
            return []


async def scan_token_security(chain_id: str, token_address: str) -> dict | None:
    """GoPlus Security scan."""
    url = f"https://api.gopluslabs.io/api/v1/token_security/{chain_id}"
    async with httpx.AsyncClient(timeout=15.0) as client:
        try:
            resp = await client.get(url, params={"contract_addresses": token_address})
            resp.raise_for_status()
            result = resp.json().get("result", {}).get(token_address.lower(), {})
            if result:
                score = 0
                if result.get("is_honeypot") == "1":
                    score += 50
                if result.get("can_take_back_ownership") == "1":
                    score += 20
                if result.get("is_open_source") == "0":
                    score += 15
                if result.get("is_blacklisted") == "1":
                    score += 40
                buy_tax = float(result.get("buy_tax", "0"))
                sell_tax = float(result.get("sell_tax", "0"))
                if buy_tax > 10:
                    score += 15
                if sell_tax > 10:
                    score += 15
                if buy_tax > 50 or sell_tax > 50:
                    score += 20
                if result.get("is_proxy") == "1":
                    score += 10
                if result.get("is_mintable") == "1":
                    score += 10

                return {
                    "honeypot": result.get("is_honeypot") == "1",
                    "buy_tax": buy_tax,
                    "sell_tax": sell_tax,
                    "risk_score": min(100, max(0, score)),
                    "scanned_at": datetime.now(UTC).isoformat(),
                }
        except Exception as e:
            logger.warning(f"GoPlus {token_address}: {e}")
    return None


async def discover_tokens(chains: list[str] | None = None) -> dict:
    """Discover new tokens across chains. Returns {chain: [tokens]}."""
    if chains is None:
        chains = list(MONITORED_CHAINS.keys())

    result = {}
    for chain in chains:
        MONITORED_CHAINS.get(chain, chain)
        tokens = []
        seen = set()

        # DexScreener
        pairs = await fetch_dexscreener_new_pairs(chain)
        for pair in pairs:
            base = pair.get("baseToken", {})
            addr = base.get("address", "").lower()
            if addr and addr not in seen:
                seen.add(addr)
                tokens.append(
                    {
                        "address": addr,
                        "name": base.get("name", ""),
                        "symbol": base.get("symbol", ""),
                        "chain": chain,
                        "dex": pair.get("dexId", ""),
                        "liquidity_usd": float(pair.get("liquidity", {}).get("usd", 0)),
                        "volume_24h": float(pair.get("volume", {}).get("h24", 0)),
                        "price_usd": float(pair.get("priceUsd", 0)),
                        "created_at": datetime.fromtimestamp(pair.get("pairCreatedAt", 0) / 1000, tz=UTC).isoformat()
                        if pair.get("pairCreatedAt")
                        else None,
                        "source": "dexscreener",
                    }
                )

        # GeckoTerminal
        pools = await fetch_gecko_new_pools(chain)
        for pool in pools:
            attrs = pool.get("attributes", {})
            rel = pool.get("relationships", {})
            base_data = rel.get("base_token", {}).get("data", {})
            addr = base_data.get("id", "").lower()
            if addr and addr not in seen:
                seen.add(addr)
                tokens.append(
                    {
                        "address": addr,
                        "name": attrs.get("name", ""),
                        "symbol": "",
                        "chain": chain,
                        "liquidity_usd": float(attrs.get("reserve_in_usd", 0)),
                        "price_usd": float(attrs.get("base_token_price_usd", 0)),
                        "source": "geckoterminal",
                    }
                )

        result[chain] = tokens

    return result
