"""Rug Munch Intelligence — MCP Server.

97 tools for scam detection, rug pull prevention, and crypto intelligence across 7 chains.
The Bloomberg of Shitcoins Terminal Ultimate Edition.

Each tool sends POST to /api/v1/x402-tools/{tool_name} with chain + params.
x402 payment is handled transparently by the backend/gateway.
"""

import os
from typing import Any

import httpx
from mcp.server.fastmcp import FastMCP

# ---------------------------------------------------------------------------
# Configuration — NO secrets, only public endpoints
# ---------------------------------------------------------------------------

API_BASE = os.environ.get("RUG_MUNCH_API_BASE", "https://mcp.rugmunch.io/api/v1")
API_KEY = os.environ.get("RUG_MUNCH_API_KEY", "")

SUPPORTED_CHAINS = ["base", "solana", "ethereum", "bsc", "arbitrum", "optimism", "polygon"]
DEFAULT_CHAIN = "solana"

# ---------------------------------------------------------------------------
# MCP Server
# ---------------------------------------------------------------------------

mcp = FastMCP(
    name="Rug Munch Intelligence",
    instructions="97 tools for scam detection, rug pull prevention, and crypto intelligence across 7 chains.",
)


# ---------------------------------------------------------------------------
# HTTP helper
# ---------------------------------------------------------------------------


async def _call_tool(tool_name: str, payload: dict[str, Any]) -> dict[str, Any]:
    """POST to the x402-tools endpoint. Payment is handled by the gateway."""
    url = f"{API_BASE}/x402-tools/{tool_name}"
    headers: dict[str, str] = {"Content-Type": "application/json"}
    if API_KEY:
        headers["Authorization"] = f"Bearer {API_KEY}"

    async with httpx.AsyncClient(timeout=30) as client:
        resp = await client.post(url, json=payload, headers=headers)
        resp.raise_for_status()
        return resp.json()


def _chain_payload(chain: str, **kwargs: Any) -> dict[str, Any]:
    """Build a standard payload with chain + extra kwargs."""
    payload: dict[str, Any] = {"chain": chain or DEFAULT_CHAIN}
    payload.update({k: v for k, v in kwargs.items() if v is not None})
    return payload


# ===========================================================================
# INTELLIGENCE (28 tools)
# ===========================================================================


@mcp.tool()
async def whale_scan(chain: str = DEFAULT_CHAIN, address: str | None = None, min_usd: float | None = None) -> dict:
    """Track whale wallet movements and large transactions."""
    return await _call_tool("whale_scan", _chain_payload(chain, address=address, min_usd=min_usd))


@mcp.tool()
async def smartmoney(chain: str = DEFAULT_CHAIN, address: str | None = None, timeframe: str | None = None) -> dict:
    """Identify smart money wallets and their positions."""
    return await _call_tool("smartmoney", _chain_payload(chain, address=address, timeframe=timeframe))


@mcp.tool()
async def cluster(chain: str = DEFAULT_CHAIN, address: str | None = None, depth: int | None = None) -> dict:
    """Cluster related wallets by behavior patterns."""
    return await _call_tool("cluster", _chain_payload(chain, address=address, depth=depth))


@mcp.tool()
async def airdrop_finder(chain: str = DEFAULT_CHAIN, address: str | None = None) -> dict:
    """Find eligible airdrops for a wallet."""
    return await _call_tool("airdrop_finder", _chain_payload(chain, address=address))


@mcp.tool()
async def whale_profile(chain: str = DEFAULT_CHAIN, address: str | None = None) -> dict:
    """Deep profile of a whale wallet's history."""
    return await _call_tool("whale_profile", _chain_payload(chain, address=address))


@mcp.tool()
async def insider(chain: str = DEFAULT_CHAIN, token: str | None = None) -> dict:
    """Detect insider trading patterns before launches."""
    return await _call_tool("insider", _chain_payload(chain, token=token))


@mcp.tool()
async def smart_money_alpha(chain: str = DEFAULT_CHAIN, token: str | None = None) -> dict:
    """Alpha signals from smart money activity."""
    return await _call_tool("smart_money_alpha", _chain_payload(chain, token=token))


@mcp.tool()
async def social_signal(chain: str = DEFAULT_CHAIN, token: str | None = None) -> dict:
    """Social media signal aggregation for tokens."""
    return await _call_tool("social_signal", _chain_payload(chain, token=token))


@mcp.tool()
async def sentiment(chain: str = DEFAULT_CHAIN, token: str | None = None) -> dict:
    """Market sentiment analysis across sources."""
    return await _call_tool("sentiment", _chain_payload(chain, token=token))


@mcp.tool()
async def copy_trade_finder(chain: str = DEFAULT_CHAIN, address: str | None = None) -> dict:
    """Find wallets worth copy-trading."""
    return await _call_tool("copy_trade_finder", _chain_payload(chain, address=address))


@mcp.tool()
async def liquidity_flow(chain: str = DEFAULT_CHAIN, token: str | None = None) -> dict:
    """Track liquidity inflows and outflows."""
    return await _call_tool("liquidity_flow", _chain_payload(chain, token=token))


@mcp.tool()
async def risk_monitor(chain: str = DEFAULT_CHAIN, token: str | None = None) -> dict:
    """Continuous risk monitoring for positions."""
    return await _call_tool("risk_monitor", _chain_payload(chain, token=token))


@mcp.tool()
async def rug_pull_predictor(chain: str = DEFAULT_CHAIN, token: str | None = None) -> dict:
    """ML-based rug pull prediction scoring."""
    return await _call_tool("rug_pull_predictor", _chain_payload(chain, token=token))


@mcp.tool()
async def meme_vibe_score(chain: str = DEFAULT_CHAIN, token: str | None = None) -> dict:
    """Meme coin community vibe and virality scoring."""
    return await _call_tool("meme_vibe_score", _chain_payload(chain, token=token))


@mcp.tool()
async def nft_wash_detector(chain: str = DEFAULT_CHAIN, collection: str | None = None) -> dict:
    """Detect NFT wash trading patterns."""
    return await _call_tool("nft_wash_detector", _chain_payload(chain, collection=collection))


@mcp.tool()
async def gas_forecast(chain: str = DEFAULT_CHAIN) -> dict:
    """Gas price forecasting and optimization."""
    return await _call_tool("gas_forecast", _chain_payload(chain))


@mcp.tool()
async def bridge_security(chain: str = DEFAULT_CHAIN, bridge: str | None = None) -> dict:
    """Cross-chain bridge risk assessment."""
    return await _call_tool("bridge_security", _chain_payload(chain, bridge=bridge))


@mcp.tool()
async def defi_yield_scanner(chain: str = DEFAULT_CHAIN, protocol: str | None = None) -> dict:
    """Scan DeFi yields and risk-adjusted returns."""
    return await _call_tool("defi_yield_scanner", _chain_payload(chain, protocol=protocol))


@mcp.tool()
async def portfolio_tracker(chain: str = DEFAULT_CHAIN, address: str | None = None) -> dict:
    """Track and analyze portfolio composition."""
    return await _call_tool("portfolio_tracker", _chain_payload(chain, address=address))


@mcp.tool()
async def token_deep_dive(chain: str = DEFAULT_CHAIN, token: str | None = None) -> dict:
    """Deep fundamental analysis of any token."""
    return await _call_tool("token_deep_dive", _chain_payload(chain, token=token))


@mcp.tool()
async def token_comparison(chain: str = DEFAULT_CHAIN, token_a: str | None = None, token_b: str | None = None) -> dict:
    """Side-by-side token comparison analysis."""
    return await _call_tool("token_comparison", _chain_payload(chain, token_a=token_a, token_b=token_b))


@mcp.tool()
async def forensic_valuation(chain: str = DEFAULT_CHAIN, token: str | None = None) -> dict:
    """Forensic-based token valuation modeling."""
    return await _call_tool("forensic_valuation", _chain_payload(chain, token=token))


@mcp.tool()
async def comprehensive_audit(chain: str = DEFAULT_CHAIN, token: str | None = None) -> dict:
    """Full-scope audit of a token or contract."""
    return await _call_tool("comprehensive_audit", _chain_payload(chain, token=token))


@mcp.tool()
async def investigation_report(chain: str = DEFAULT_CHAIN, token: str | None = None) -> dict:
    """Generate detailed investigation reports."""
    return await _call_tool("investigation_report", _chain_payload(chain, token=token))


@mcp.tool()
async def market_overview(chain: str = DEFAULT_CHAIN) -> dict:
    """Real-time market overview and metrics."""
    return await _call_tool("market_overview", _chain_payload(chain))


@mcp.tool()
async def chain_health(chain: str = DEFAULT_CHAIN) -> dict:
    """Blockchain network health and congestion metrics."""
    return await _call_tool("chain_health", _chain_payload(chain))


@mcp.tool()
async def anomaly(chain: str = DEFAULT_CHAIN, token: str | None = None) -> dict:
    """Detect anomalous on-chain behavior."""
    return await _call_tool("anomaly", _chain_payload(chain, token=token))


@mcp.tool()
async def honeypot_check(chain: str = DEFAULT_CHAIN, token: str | None = None) -> dict:
    """Check if a token is a honeypot scam."""
    return await _call_tool("honeypot_check", _chain_payload(chain, token=token))


@mcp.tool()
async def mev_protection(chain: str = DEFAULT_CHAIN) -> dict:
    """Assess MEV exposure and protection strategies."""
    return await _call_tool("mev_protection", _chain_payload(chain))


# ===========================================================================
# SECURITY (17 tools) — some shared names, different tool registration context
# ===========================================================================


@mcp.tool()
async def urlcheck(url: str | None = None) -> dict:
    """Check URLs for phishing and scam indicators."""
    return await _call_tool("urlcheck", {"url": url} if url else {})


@mcp.tool()
async def rugshield(chain: str = DEFAULT_CHAIN, token: str | None = None) -> dict:
    """Real-time rug pull shield and protection."""
    return await _call_tool("rugshield", _chain_payload(chain, token=token))


@mcp.tool()
async def clone_detect(chain: str = DEFAULT_CHAIN, token: str | None = None) -> dict:
    """Detect cloned/fake tokens and contracts."""
    return await _call_tool("clone_detect", _chain_payload(chain, token=token))


@mcp.tool()
async def fresh_pair(chain: str = DEFAULT_CHAIN, pair: str | None = None) -> dict:
    """Analyze freshly launched trading pairs."""
    return await _call_tool("fresh_pair", _chain_payload(chain, pair=pair))


@mcp.tool()
async def profile_flip(chain: str = DEFAULT_CHAIN, token: str | None = None) -> dict:
    """Profile flip risk for token distributions."""
    return await _call_tool("profile_flip", _chain_payload(chain, token=token))


@mcp.tool()
async def audit(chain: str = DEFAULT_CHAIN, contract: str | None = None) -> dict:
    """Smart contract security audit."""
    return await _call_tool("audit", _chain_payload(chain, contract=contract))


# ===========================================================================
# MARKET (14 tools)
# ===========================================================================


@mcp.tool()
async def pulse(chain: str = DEFAULT_CHAIN) -> dict:
    """Real-time market pulse and momentum."""
    return await _call_tool("pulse", _chain_payload(chain))


@mcp.tool()
async def coingecko_global(chain: str = DEFAULT_CHAIN) -> dict:
    """Global market data from CoinGecko."""
    return await _call_tool("coingecko_global", _chain_payload(chain))


@mcp.tool()
async def coingecko_trending(chain: str = DEFAULT_CHAIN) -> dict:
    """Trending tokens on CoinGecko."""
    return await _call_tool("coingecko_trending", _chain_payload(chain))


@mcp.tool()
async def coingecko_markets(chain: str = DEFAULT_CHAIN, category: str | None = None) -> dict:
    """Market cap and volume data."""
    return await _call_tool("coingecko_markets", _chain_payload(chain, category=category))


@mcp.tool()
async def coingecko_categories(chain: str = DEFAULT_CHAIN) -> dict:
    """CoinGecko category analysis."""
    return await _call_tool("coingecko_categories", _chain_payload(chain))


# ===========================================================================
# ANALYSIS (12 tools)
# ===========================================================================


@mcp.tool()
async def tx_decoder(chain: str = DEFAULT_CHAIN, tx_hash: str | None = None) -> dict:
    """Decode and interpret transactions."""
    return await _call_tool("tx_decoder", _chain_payload(chain, tx_hash=tx_hash))


@mcp.tool()
async def wallet(chain: str = DEFAULT_CHAIN, address: str | None = None) -> dict:
    """Comprehensive wallet analysis."""
    return await _call_tool("wallet", _chain_payload(chain, address=address))


@mcp.tool()
async def contract_info(chain: str = DEFAULT_CHAIN, address: str | None = None) -> dict:
    """Extract smart contract information."""
    return await _call_tool("contract_info", _chain_payload(chain, address=address))


@mcp.tool()
async def storage_reader(chain: str = DEFAULT_CHAIN, contract: str | None = None, slot: str | None = None) -> dict:
    """Read contract storage slots."""
    return await _call_tool("storage_reader", _chain_payload(chain, contract=contract, slot=slot))


# ===========================================================================
# FORENSICS (7 tools)
# ===========================================================================


@mcp.tool()
async def forensics_threat_check(chain: str = DEFAULT_CHAIN, address: str | None = None) -> dict:
    """Threat intelligence check for addresses."""
    return await _call_tool("forensics_threat_check", _chain_payload(chain, address=address))


@mcp.tool()
async def forensics_risk_report(chain: str = DEFAULT_CHAIN, address: str | None = None) -> dict:
    """Detailed forensics risk report."""
    return await _call_tool("forensics_risk_report", _chain_payload(chain, address=address))


@mcp.tool()
async def forensics_deep_scan(chain: str = DEFAULT_CHAIN, address: str | None = None) -> dict:
    """Deep forensic scan of wallet/activity."""
    return await _call_tool("forensics_deep_scan", _chain_payload(chain, address=address))


@mcp.tool()
async def forensics_cross_chain(chain: str = DEFAULT_CHAIN, address: str | None = None) -> dict:
    """Cross-chain forensic correlation."""
    return await _call_tool("forensics_cross_chain", _chain_payload(chain, address=address))


@mcp.tool()
async def bundle_security_pack(chain: str = DEFAULT_CHAIN, token: str | None = None) -> dict:
    """Bundle of security forensics tools."""
    return await _call_tool("bundle_security_pack", _chain_payload(chain, token=token))


@mcp.tool()
async def forensics_trace(chain: str = DEFAULT_CHAIN, address: str | None = None, depth: int | None = None) -> dict:
    """Trace funds through complex transaction graphs."""
    return await _call_tool("forensics_trace", _chain_payload(chain, address=address, depth=depth))


@mcp.tool()
async def forensics_entity(chain: str = DEFAULT_CHAIN, address: str | None = None) -> dict:
    """Entity resolution from on-chain footprints."""
    return await _call_tool("forensics_entity", _chain_payload(chain, address=address))


# ===========================================================================
# SOCIAL (7 tools)
# ===========================================================================


@mcp.tool()
async def tw_profile(username: str | None = None) -> dict:
    """Twitter/X profile analysis."""
    payload = {"chain": DEFAULT_CHAIN}
    if username:
        payload["username"] = username
    return await _call_tool("tw_profile", payload)


@mcp.tool()
async def tw_timeline(username: str | None = None, limit: int | None = None) -> dict:
    """Twitter/X timeline analysis."""
    payload: dict[str, Any] = {"chain": DEFAULT_CHAIN}
    if username:
        payload["username"] = username
    if limit:
        payload["limit"] = limit
    return await _call_tool("tw_timeline", payload)


@mcp.tool()
async def tw_search(query: str | None = None) -> dict:
    """Twitter/X search for crypto mentions."""
    payload: dict[str, Any] = {"chain": DEFAULT_CHAIN}
    if query:
        payload["query"] = query
    return await _call_tool("tw_search", payload)


@mcp.tool()
async def profile_get(address: str | None = None) -> dict:
    """Get Rug Munch user profile."""
    payload: dict[str, Any] = {"chain": DEFAULT_CHAIN}
    if address:
        payload["address"] = address
    return await _call_tool("profile_get", payload)


@mcp.tool()
async def profile_badges(address: str | None = None) -> dict:
    """Get user badges and reputation."""
    payload: dict[str, Any] = {"chain": DEFAULT_CHAIN}
    if address:
        payload["address"] = address
    return await _call_tool("profile_badges", payload)


# ===========================================================================
# OSINT (3 tools)
# ===========================================================================


@mcp.tool()
async def osint_search(query: str | None = None) -> dict:
    """Open source intelligence search."""
    payload: dict[str, Any] = {"chain": DEFAULT_CHAIN}
    if query:
        payload["query"] = query
    return await _call_tool("osint_search", payload)


@mcp.tool()
async def osint_identity_hunt(identifier: str | None = None) -> dict:
    """Cross-reference identities across platforms."""
    payload: dict[str, Any] = {"chain": DEFAULT_CHAIN}
    if identifier:
        payload["identifier"] = identifier
    return await _call_tool("osint_identity_hunt", payload)


@mcp.tool()
async def osint_investigate(target: str | None = None) -> dict:
    """Deep OSINT investigation."""
    payload: dict[str, Any] = {"chain": DEFAULT_CHAIN}
    if target:
        payload["target"] = target
    return await _call_tool("osint_investigate", payload)


# ===========================================================================
# LAUNCHPAD (3 tools)
# ===========================================================================


@mcp.tool()
async def launch(chain: str = DEFAULT_CHAIN) -> dict:
    """Track token launches in real-time."""
    return await _call_tool("launch", _chain_payload(chain))


@mcp.tool()
async def launch_intel(chain: str = DEFAULT_CHAIN) -> dict:
    """Intelligence on upcoming launches."""
    return await _call_tool("launch_intel", _chain_payload(chain))


@mcp.tool()
async def sniper_alert(chain: str = DEFAULT_CHAIN) -> dict:
    """Snipe alerts for high-potential launches."""
    return await _call_tool("sniper_alert", _chain_payload(chain))


# ===========================================================================
# META (3 tools)
# ===========================================================================


@mcp.tool()
async def list_bundles() -> dict:
    """List available tool bundles."""
    return await _call_tool("list_bundles", {"chain": DEFAULT_CHAIN})


@mcp.tool()
async def tools_discovery() -> dict:
    """Discover all available tools."""
    return await _call_tool("tools_discovery", {"chain": DEFAULT_CHAIN})


@mcp.tool()
async def framework_discovery() -> dict:
    """Discover framework capabilities."""
    return await _call_tool("framework_discovery", {"chain": DEFAULT_CHAIN})


# ===========================================================================
# NEWS (3 tools)
# ===========================================================================


@mcp.tool()
async def news_headlines(category: str | None = None) -> dict:
    """Latest crypto news headlines."""
    payload: dict[str, Any] = {"chain": DEFAULT_CHAIN}
    if category:
        payload["category"] = category
    return await _call_tool("news_headlines", payload)


@mcp.tool()
async def news_twitter(query: str | None = None) -> dict:
    """Crypto news from Twitter/X."""
    payload: dict[str, Any] = {"chain": DEFAULT_CHAIN}
    if query:
        payload["query"] = query
    return await _call_tool("news_twitter", payload)


@mcp.tool()
async def news_combined(category: str | None = None) -> dict:
    """Combined news from all sources."""
    payload: dict[str, Any] = {"chain": DEFAULT_CHAIN}
    if category:
        payload["category"] = category
    return await _call_tool("news_combined", payload)


# ===========================================================================
# Entry point
# ===========================================================================


def main():
    """Run the Rug Munch Intelligence MCP server."""
    mcp.run()


if __name__ == "__main__":
    main()
