"""
x402 Router: contract_upgrade_monitor
========================================
Wraps ContractUpgradeAnalyzer with:
  - Address validation
  - x402 payment middleware integration
  - Caching (Redis if available)
  - Trial quota tracking
  - Rate limiting support

TOOL  : contract_upgrade_monitor
TIER  : security
PRICE : $0.05 (50000 atoms)
TRIAL : 2 free checks
ROUTER: /api/v1/x402-tools/contract_upgrade_monitor
"""

from __future__ import annotations

import json
import logging
import os
from contextlib import suppress

import redis as _redis_mod
from fastapi import APIRouter, HTTPException, Request
from pydantic import BaseModel, Field, field_validator

from app.contract_upgrade_monitor import (
    format_upgrade_report,
    get_upgrade_analyzer,
    is_valid_evm_address,
)

logger = logging.getLogger("x402_contract_upgrade_monitor")

router = APIRouter(prefix="/api/v1/x402-tools", tags=["x402-tools"])

# ── Redis helpers ─────────────────────────────────────────────

_redis: _redis_mod.Redis | None = None


def _get_redis():
    global _redis
    if _redis is None:
        try:
            r = _redis_mod.Redis(
                host=os.getenv("REDIS_HOST", "localhost"),
                port=int(os.getenv("REDIS_PORT", 6379)),
                db=int(os.getenv("REDIS_DB", 0)),
                password=os.getenv("REDIS_PASSWORD", None),
                decode_responses=True,
            )
            r.ping()
            _redis = r
        except Exception:
            _redis = None  # Not available
    return _redis


_CACHE_TTL = 600  # 10 minutes - upgrade data doesn't change rapidly


# ── Request Models ─────────────────────────────────────────────


class ContractUpgradeRequest(BaseModel):
    """Request body for contract upgrade monitoring."""

    contract_address: str = Field(
        ...,
        description="EVM contract address to check for proxy upgrade risk",
        min_length=42,
        max_length=42,
    )
    chain: str = Field(
        default="ethereum",
        description="Chain name (ethereum, bsc, polygon, arbitrum, optimism, base, avalanche)",
    )

    @field_validator("contract_address")
    @classmethod
    def validate_address(cls, v: str) -> str:
        v = v.strip()
        if not is_valid_evm_address(v):
            raise ValueError(f"Invalid EVM address: {v}. Must be a 0x-prefixed 40-char hex address.")
        return v

    @field_validator("chain")
    @classmethod
    def validate_chain(cls, v: str) -> str:
        valid = {"ethereum", "bsc", "polygon", "arbitrum", "optimism", "base", "avalanche"}
        v = v.strip().lower()
        if v not in valid:
            raise ValueError(f"Unsupported chain: {v}. Supported: {', '.join(sorted(valid))}")
        return v


# ── Endpoints ──────────────────────────────────────────────────


@router.post("/contract_upgrade_monitor")
async def analyze_contract_upgrades(request: Request, body: ContractUpgradeRequest) -> dict:
    """
    Monitor proxy contract upgrades for malicious implementation swaps.
    Detects EIP-1967, EIP-1822 UUPS, Beacon, and Gnosis Safe proxies.
    Returns upgrade history, timelock status, and risk assessment (0-100).
    """
    address = body.contract_address.strip()
    chain = body.chain.strip().lower()

    # Check cache
    cache_key = f"contract_upgrade_monitor:{address}:{chain}"
    r = _get_redis()
    if r:
        with suppress(Exception):
            cached = r.get(cache_key)
            if cached:
                return json.loads(cached)

    # Check trial quota (via x402 middleware headers if available)
    trial_used = False
    x402_headers = getattr(request.state, "x402", None) or {}
    quota = x402_headers.get("remaining_quota", {})
    if isinstance(quota, dict) and quota.get("contract_upgrade_monitor", 0) > 0:
        trial_used = True
        logger.info(
            "Trial quota used for contract_upgrade_monitor on %s (%s)",
            address[:10],
            chain,
        )

    try:
        analyzer = get_upgrade_analyzer()
        report = await analyzer.analyze(
            contract_address=address,
            chain=chain,
        )

        response = {
            "success": True,
            "tool": "contract_upgrade_monitor",
            "contract_address": address,
            "chain": chain,
            "is_proxy": report.proxy_info.is_proxy if report.proxy_info else False,
            "proxy_type": report.proxy_info.proxy_type if report.proxy_info else None,
            "proxy_type_name": report.proxy_info.proxy_type_name if report.proxy_info else None,
            "implementation_address": report.proxy_info.implementation_address if report.proxy_info else None,
            "admin_address": report.proxy_info.admin_address if report.proxy_info else None,
            "beacon_address": report.proxy_info.beacon_address if report.proxy_info else None,
            "timelock_status": report.timelock_status,
            "upgrade_count_30d": report.upgrade_count_30d,
            "upgrade_history_count": len(report.upgrade_history),
            "recent_suspicious_upgrades": len(report.recent_suspicious_upgrades),
            "implementation_age_days": report.implementation_age_days,
            "admin_privileges": report.admin_privileges[:10],
            "risk_score": report.risk_score,
            "risk_factors": report.risk_factors[:10],
            "summary": report.summary,
            "report_text": format_upgrade_report(report),
            "trial_used": trial_used,
        }

        # Cache only paid results (not trial)
        if not trial_used and r:
            with suppress(Exception):
                r.setex(cache_key, _CACHE_TTL, json.dumps(response))

        return response

    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e)) from e
    except Exception as e:
        logger.exception("Contract upgrade monitor failed for %s on %s", address[:10], chain)
        raise HTTPException(
            status_code=500,
            detail=f"Analysis failed: {e!s}",
        ) from e


@router.get("/contract_upgrade_monitor/health")
async def contract_upgrade_health() -> dict:
    """Health check endpoint."""
    return {
        "status": "ok",
        "tool": "contract_upgrade_monitor",
        "version": "1.0.0",
    }
