#!/usr/bin/env python3
"""#12 - Multi-Chain Airdrop Scanner. Scans address across all chains for unclaimed airdrops,
governance tokens, dust that became valuable. Free tier shows value, paid tier auto-claims."""

import asyncio
import os
from typing import Any

import httpx
from fastapi import APIRouter, Query

router = APIRouter(prefix="/api/v1/airdrop-scanner", tags=["airdrop-scanner"])

DATABUS = os.environ.get("DATABUS_URL", "http://localhost:8000/api/v1/databus")

CHAINS = [
    "solana",
    "ethereum",
    "bsc",
    "base",
    "arbitrum",
    "polygon",
    "avalanche",
    "optimism",
    "fantom",
    "linea",
    "zksync",
    "scroll",
]

KNOWN_AIRDROPS = {
    "ethereum": [
        {"project": "Uniswap", "token": "UNI", "check_contract": "0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"},
        {"project": "ENS", "token": "ENS", "check_contract": "0xC18360217D8F7Ab5e7c516566761Ea12Ce7F9D72"},
    ],
    "arbitrum": [
        {"project": "Arbitrum", "token": "ARB", "check_contract": "0x912CE59144191C1204E64559FE8253a0e49E6548"},
    ],
    "solana": [
        {"project": "Jupiter", "token": "JUP", "check_contract": "JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN"},
        {"project": "Pyth", "token": "PYTH", "check_contract": "HZ1JovNiVvGrGNiiYvEozEVgZ58xaU3RKwX8eACQBCt3"},
        {"project": "Jito", "token": "JTO", "check_contract": "jtojtomepa8beP8AuQc6eXt5FriJwfFMwQx2v2f9mCL"},
    ],
}


async def _check_chain_airdrops(address: str, chain: str) -> dict[str, Any]:
    """Check for unclaimed airdrops on a single chain."""
    found: list[dict] = []
    total_value = 0.0

    known = KNOWN_AIRDROPS.get(chain, [])
    for airdrop in known:
        try:
            async with httpx.AsyncClient(timeout=8) as client:
                resp = await client.get(
                    f"{DATABUS}/{chain}/balance/{address}", params={"token": airdrop["check_contract"]}
                )
                if resp.status_code == 200:
                    data = resp.json().get("data", {})
                    balance = float(data.get("balance", 0) or 0)
                    value = float(data.get("value_usd", 0) or 0)
                    if balance > 0:
                        found.append(
                            {
                                "project": airdrop["project"],
                                "token": airdrop["token"],
                                "chain": chain,
                                "balance": balance,
                                "value_usd": round(value, 2),
                                "claimable": False,  # Would need per-project claim logic
                            }
                        )
                        total_value += value
        except Exception:
            continue

    return {"chain": chain, "airdrops": found, "total_value": round(total_value, 2)}


@router.get("/scan/{address}")
async def scan_airdrops(address: str, chains: str = Query(None)):
    """Scan an address across all chains for unclaimed airdrops."""
    chain_list = chains.split(",") if chains else CHAINS[:8]

    tasks = []
    for c in chain_list:
        if c in KNOWN_AIRDROPS:
            tasks.append(_check_chain_airdrops(address, c))

    results = await asyncio.gather(*tasks)
    all_airdrops = []
    grand_total = 0.0
    for r in results:
        all_airdrops.extend(r["airdrops"])
        grand_total += r["total_value"]

    return {
        "address": address,
        "chains_scanned": len(results),
        "airdrops_found": len(all_airdrops),
        "total_value_usd": round(grand_total, 2),
        "airdrops": all_airdrops,
    }


@router.get("/known-projects")
async def list_known_airdrops():
    """List all known airdrop projects by chain."""
    return {"airdrops": KNOWN_AIRDROPS, "total_chains": len(KNOWN_AIRDROPS)}


@router.get("/dust-check/{address}")
async def check_dust(address: str, chain: str = Query("solana")):
    """Check for dust tokens that might have become valuable."""
    try:
        async with httpx.AsyncClient(timeout=10) as client:
            resp = await client.get(f"{DATABUS}/{chain}/tokens/{address}")
            if resp.status_code != 200:
                return {"address": address, "chain": chain, "tokens": [], "error": "chain unavailable"}
            tokens = resp.json().get("data", {}).get("tokens", [])
            # Find tokens with small balances that have value
            dust_tokens = []
            for t in tokens:
                bal = float(t.get("balance", 0) or 0)
                val = float(t.get("value_usd", 0) or 0)
                if bal > 0 and val > 0:
                    dust_tokens.append({"token": t.get("symbol", "?"), "balance": bal, "value_usd": round(val, 2)})
            dust_tokens.sort(key=lambda t: t["value_usd"], reverse=True)
            total_dust = sum(t["value_usd"] for t in dust_tokens)
            return {
                "address": address,
                "chain": chain,
                "dust_tokens": dust_tokens[:20],
                "total_dust_value": round(total_dust, 2),
            }
    except Exception as e:
        return {"address": address, "chain": chain, "error": str(e)}
