#!/usr/bin/env python3
"""#1 - MEV Sniper Dashboard. Real-time new pair signals + SENTINEL risk scoring.
Surfaces snipeable launches across all chains with safety filtering."""

import os
from datetime import UTC, datetime, timedelta
from typing import Any

import httpx
from fastapi import APIRouter, Query
from pydantic import BaseModel

router = APIRouter(prefix="/api/v1/mev-sniper", tags=["mev-sniper"])

DEXSCREENER = "https://api.dexscreener.com/latest/dex/search"
BACKEND = os.environ.get("BACKEND_URL", "http://localhost:8000")
CHAINS = ["solana", "ethereum", "bsc", "base", "arbitrum", "polygon", "avalanche"]


class SnipeSignal(BaseModel):
    chain: str
    symbol: str
    address: str
    price_usd: float
    liquidity_usd: float
    volume_24h: float
    age_minutes: int
    safety_score: int
    risk_flags: list[str]
    snipe_score: int = 0  # 0-100, composite attractiveness


async def _get_new_pairs(chain: str, max_age_min: int = 30) -> list[dict]:
    """Fetch newly created pairs from DexScreener."""
    pairs = []
    try:
        async with httpx.AsyncClient(timeout=10) as client:
            resp = await client.get(f"{DEXSCREENER}?q={chain}")
            if resp.status_code != 200:
                return []
            all_pairs = resp.json().get("pairs", [])
            cutoff = (datetime.now(UTC) - timedelta(minutes=max_age_min)).timestamp() * 1000
            pairs = [p for p in all_pairs if p.get("pairCreatedAt", 0) > cutoff]
    except Exception:
        pass
    return pairs


def _compute_snipe_score(liquidity: float, volume: float, age_min: int, safety: int) -> int:
    """Composite attractiveness score for sniping."""
    score = 50
    if liquidity > 50000:
        score += 15
    elif liquidity > 10000:
        score += 8
    if volume > liquidity * 0.5:
        score += 15  # active trading
    if age_min < 5:
        score += 10  # fresh
    if age_min < 15:
        score += 5
    score += (safety - 50) * 0.3  # safety adjustment
    return min(100, max(0, int(score)))


@router.get("/signals")
async def get_snipe_signals(
    chain: str = "solana",
    max_age_min: int = Query(30, ge=1, le=120),
    min_liquidity: float = Query(5000, ge=0),
    min_safety: int = Query(30, ge=0, le=100),
    limit: int = Query(20, le=50),
):
    """Get real-time snipe signals for a chain. Sorted by snipe_score descending."""
    pairs = await _get_new_pairs(chain, max_age_min)
    signals: list[dict[str, Any]] = []

    for p in pairs[: limit * 2]:
        base = p.get("baseToken", {})
        addr = p.get("pairAddress", "") or base.get("address", "")
        liq = p.get("liquidity", {}).get("usd", 0) or 0
        if liq < min_liquidity:
            continue

        created_at = p.get("pairCreatedAt", 0) / 1000
        age_min = int((datetime.now(UTC).timestamp() - created_at) / 60) if created_at else 99

        # Quick safety check via internal API
        safety = 50
        flags: list[str] = []
        try:
            async with httpx.AsyncClient(timeout=5) as client:
                resp = await client.post(
                    f"{BACKEND}/api/v1/token/scan",
                    json={"token_address": addr, "chain": chain},
                    headers={"X-RMI-Key": "rmi-internal-2026"},
                )
                if resp.status_code == 200:
                    data = resp.json()
                    safety = data.get("safety_score", 50)
                    flags = data.get("risk_flags", [])
        except Exception:
            pass

        if safety < min_safety:
            continue

        snipe = _compute_snipe_score(liq, p.get("volume", {}).get("h24", 0) or 0, age_min, safety)
        signals.append(
            {
                "chain": chain,
                "symbol": base.get("symbol", "?"),
                "address": addr,
                "price_usd": float(p.get("priceUsd", 0) or 0),
                "liquidity_usd": liq,
                "volume_24h": float(p.get("volume", {}).get("h24", 0) or 0),
                "age_minutes": age_min,
                "safety_score": safety,
                "risk_flags": flags,
                "snipe_score": snipe,
            }
        )

    signals.sort(key=lambda s: s["snipe_score"], reverse=True)
    return {"chain": chain, "count": len(signals[:limit]), "signals": signals[:limit]}


@router.get("/chains")
async def list_sniper_chains():
    return {"chains": CHAINS}
