"""RMI Backend - Application lifespan (startup/shutdown events)."""

import asyncio
import os

import httpx
from fastapi import FastAPI

from app.core.logging import get_logger

logger = get_logger(__name__)

# Background task imports (lazy, at startup time)


async def lifespan(app: FastAPI):
    """Application lifespan: startup checks, background tasks, graceful shutdown."""
    vault_pw = os.getenv("WALLET_VAULT_PASSWORD", "").strip()
    if not vault_pw:
        raise RuntimeError(
            "CRITICAL: WALLET_VAULT_PASSWORD environment variable is missing or empty. "
            "The backend will not start without it to prevent silent wallet key loss."
        )

    app.state.http_client = httpx.AsyncClient(
        limits=httpx.Limits(max_connections=100, max_keepalive_connections=20), timeout=10.0
    )

    await _verify_indexes(app)
    await _start_background_tasks(app)

    yield  # App runs here

    await app.state.http_client.aclose()
    logger.info("shutdown_complete")


async def _start_background_tasks(app: FastAPI) -> None:
    """Start all background monitoring / cleanup tasks."""
    tasks = [
        ("facilitator_health", "app.routers.facilitator_health", "health_check_loop", "60s"),
        ("status_page", "app.routers.status_page", "status_monitor_loop", "30s"),
        ("webhook_dispatcher", "app.routers.webhook_dispatcher", "webhook_dispatcher_loop", "5s"),
        ("x402_trial_cleanup", "app.routers.x402_enforcement", "trial_cleanup_loop", "hourly"),
        ("auto_sweep", "app.wallet_manager_v2", "auto_sweep_loop", ""),
    ]

    for name, module_path, func_name, interval in tasks:
        try:
            mod = __import__(module_path, fromlist=[func_name])
            fn = getattr(mod, func_name)
            if name == "auto_sweep":
                asyncio.create_task(fn())
            else:
                asyncio.create_task(fn())
            logger.info("background_task_started", task=name, interval=interval)
        except Exception as e:
            logger.warning("background_task_failed", task=name, error=str(e))

    # Cache warmer (passes app instance)
    try:
        from app.databus.core import cache_warm_loop

        asyncio.create_task(cache_warm_loop(app))
        logger.info("background_task_started", task="databus_cache_warmer", interval="")
    except Exception as e:
        logger.warning("background_task_failed", task="databus_cache_warmer", error=str(e))


async def _verify_indexes(app: FastAPI) -> None:
    """Verify and create database indexes on startup."""
    try:
        supabase_url = os.getenv("SUPABASE_URL", "")
        supabase_key = os.getenv("SUPABASE_SERVICE_KEY", "") or os.getenv("SUPABASE_KEY", "")
        if not supabase_url or not supabase_key:
            return

        indexes = [
            "CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_scan_results_created_at ON scan_results(created_at DESC);",
            "CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_scan_results_token_address ON scan_results(token_address);",
            "CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_whale_alerts_created_at ON whale_alerts(created_at DESC);",
            "CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_security_alerts_created_at ON security_alerts(created_at DESC);",
            "CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_x402_payments_tx_hash ON x402_payments(tx_hash);",
        ]

        for sql in indexes:
            try:
                res = await app.state.http_client.post(
                    f"{supabase_url}/rest/v1/rpc/exec_sql",
                    json={"query": sql},
                    headers={
                        "apikey": supabase_key,
                        "Authorization": f"Bearer {supabase_key}",
                        "Content-Type": "application/json",
                    },
                )
                if res.status_code in [200, 204]:
                    logger.info("index_verified", table=sql.split("ON ")[1].split("(")[0].strip())
                else:
                    logger.warning("index_skipped", status=res.status_code, sql=sql[:50])
            except Exception as e:
                logger.warning("index_verify_failed", error=str(e))
    except Exception as e:
        logger.warning("index_verification_skipped", error=str(e))
