#!/usr/bin/env python3
"""
🌸 Nami API Gateway — Unified REST API for the Nami Army
One endpoint to rule them all.

Endpoints:
    GET  /api/status       — All services health
    GET  /api/services     — List all services
    GET  /api/agents       — Coding agent status
    GET  /api/bridge       — Nami Bridge status
    POST /api/health/check — Run health check

Run:
    python3 /opt/nami-army/api_gateway.py --port 8700
"""

import asyncio
import json
import os
import subprocess
import sys
from datetime import datetime, timezone
from pathlib import Path
from typing import Optional

# ─── Dependencies check ─────────────────────────────────────────────
try:
    from fastapi import FastAPI, HTTPException, Query
    from fastapi.middleware.cors import CORSMiddleware
    from fastapi.responses import JSONResponse, HTMLResponse
    import uvicorn
except ImportError:
    print("Installing dependencies...")
    subprocess.run([sys.executable, "-m", "pip", "install", "fastapi", "uvicorn", "-q"])
    from fastapi import FastAPI, HTTPException, Query
    from fastapi.middleware.cors import CORSMiddleware
    from fastapi.responses import JSONResponse, HTMLResponse
    import uvicorn

app = FastAPI(
    title="🌸 Nami API Gateway",
    version="1.0.0",
    description="Unified REST API for Nami Army services"
)

# CORS — allow all (for dashboard, external tools)
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_methods=["*"],
    allow_headers=["*"],
)

NAMI_DIR = Path("/opt/nami-army")

SERVICES = {
    "hermes-gateway":   {"name": "Hermes Gateway",   "emoji": "🧠", "port": 8644, "critical": True},
    "nami-bridge":      {"name": "Nami Bridge",      "emoji": "🌉", "port": 8888, "critical": True},
    "nami-status-api":   {"name": "Status API",      "emoji": "📡", "port": 8699, "critical": False},
    "laopatana-stat-lab": {"name": "LaoPatana",       "emoji": "📊", "port": 3000, "critical": False},
    "hanoi-stats-analyzer": {"name": "Hanoi Lottery",  "emoji": "🎲", "port": 3002, "critical": False},
    "clipboardbypao":   {"name": "ClipboardByPao",   "emoji": "📋", "port": 3001, "critical": False},
    "gold-signal-os":   {"name": "Gold Signal",      "emoji": "🥇", "port": 8002, "critical": False},
    "miroshark-backend": {"name": "MiroShark Backend", "emoji": "🦈", "port": 5001, "critical": False},
    "miroshark-frontend": {"name": "MiroShark Frontend","emoji": "🦈", "port": 3003, "critical": False},
    "miroshark-oracle": {"name": "MiroShark Oracle",  "emoji": "🔮", "port": 8003, "critical": False},
    "nginx":            {"name": "Nginx",            "emoji": "🌐", "critical": True},
    "postgresql":       {"name": "PostgreSQL",       "emoji": "🗄️", "critical": True},
}


def check_systemd(name: str) -> dict:
    try:
        r = subprocess.run(["systemctl", "is-active", name], capture_output=True, text=True, timeout=5)
        return {"status": "up" if r.stdout.strip() == "active" else "down", "detail": r.stdout.strip()}
    except:
        return {"status": "down", "detail": "error"}


def get_system_metrics() -> dict:
    """Get system metrics: CPU, RAM, Disk, Uptime"""
    import shutil
    metrics = {}
    # CPU — use /proc/loadavg for simplicity
    try:
        with open('/proc/loadavg') as f:
            load = f.read().split()[0]
        metrics['cpu'] = f"{float(load):.1f}"
    except:
        metrics['cpu'] = "—"
    # RAM
    try:
        mem = {}
        with open('/proc/meminfo') as f:
            for line in f:
                if 'MemTotal' in line: mem['total'] = int(line.split()[1])
                if 'MemAvailable' in line: mem['avail'] = int(line.split()[1])
        pct = (1 - mem['avail']/mem['total']) * 100
        metrics['ram'] = f"{pct:.0f}"
    except:
        metrics['ram'] = "—"
    # Disk
    try:
        usage = shutil.disk_usage('/')
        pct = (1 - usage.free/usage.total) * 100
        metrics['disk'] = f"{pct:.0f}"
    except:
        metrics['disk'] = "—"
    # Uptime
    try:
        with open('/proc/uptime') as f:
            secs = int(float(f.read().split()[0]))
        days = secs // 86400
        hours = (secs % 86400) // 3600
        mins = (secs % 3600) // 60
        parts = []
        if days: parts.append(f"{days}d")
        if hours: parts.append(f"{hours}h")
        parts.append(f"{mins}m")
        metrics['uptime'] = ' '.join(parts)
    except:
        metrics['uptime'] = "—"
    return metrics


def check_all_services() -> dict:
    results = {}
    now = datetime.now(timezone.utc).isoformat()
    for svc_id, svc_def in SERVICES.items():
        if "port" in svc_def and svc_def.get("type") != "systemd_only":
            # Check both systemd and port
            sysd = check_systemd(svc_id) if svc_id not in ("hermes-gateway",) else {"status": "up", "detail": "managed by hermes"}
        else:
            sysd = check_systemd(svc_id)
        
        results[svc_id] = {
            "name": svc_def["name"],
            "emoji": svc_def["emoji"],
            "status": sysd["status"],
            "detail": sysd.get("detail", ""),
            "critical": svc_def.get("critical", False),
            "checked_at": now
        }
    return results


# ─── API Endpoints ──────────────────────────────────────────────────

@app.get("/", response_class=HTMLResponse)
async def root():
    """Landing page"""
    return """
    <!DOCTYPE html>
    <html><head><title>🌸 Nami API Gateway</title>
    <style>body{font-family:system-ui;background:#0d1117;color:#c9d1d9;display:flex;align-items:center;justify-content:center;min-height:100vh;margin:0} 
    .box{text-align:center} h1{font-size:3rem} a{color:#58a6ff} code{background:#161b22;padding:2px 8px;border-radius:6px}
    </style></head><body><div class="box">
    <h1>🌸 Nami API Gateway</h1>
    <p>v1.0.0 · Unified REST API for Nami Army</p>
    <p><a href="/api/status">GET /api/status</a> — All services health</p>
    <p><a href="/api/services">GET /api/services</a> — List services</p>
    <p><a href="/api/agents">GET /api/agents</a> — Agent status</p>
    <p><a href="/api/bridge">GET /api/bridge</a> — Bridge status</p>
    <p><a href="/docs">📖 API Docs (Swagger)</a></p>
    </div></body></html>
    """


@app.get("/api/status")
async def api_status():
    """Get status of all services"""
    results = check_all_services()
    metrics = get_system_metrics()
    up = sum(1 for s in results.values() if s["status"] == "up")
    down = sum(1 for s in results.values() if s["status"] == "down")
    critical_down = sum(1 for s in results.values() if s["status"] == "down" and s.get("critical"))
    
    return {
        "ok": down == 0,
        "total": len(results),
        "up": up,
        "down": down,
        "critical_down": critical_down,
        "cpu": metrics["cpu"],
        "ram": metrics["ram"],
        "disk": metrics["disk"],
        "uptime": metrics["uptime"],
        "timestamp": datetime.now(timezone.utc).isoformat(),
        "services": results,
        "vps": "178.104.181.132",
        "name": "🌸 Nami Army"
    }


@app.get("/api/services")
async def api_services():
    """List all services with endpoints"""
    return {
        "services": [
            {"name": "🌸 Nami Dashboard", "url": "http://ecosystem.178.104.181.132.nip.io"},
            {"name": "📊 LaoPatana", "url": "http://lao.178.104.181.132.nip.io"},
            {"name": "🎲 Hanoi Stats", "url": "http://hanoi.178.104.181.132.nip.io"},
            {"name": "📋 ClipboardByPao", "url": "http://clipboardbypao.178.104.181.132.nip.io"},
            {"name": "🥇 Gold Signal", "url": "http://goldsignalos.178.104.181.132.nip.io"},
            {"name": "🦈 MiroShark", "url": "http://miroshark.178.104.181.132.nip.io"},
            {"name": "🧠 Hermes Gateway", "url": "http://178.104.181.132:8644"},
            {"name": "🌉 Nami Bridge (WS)", "url": "ws://178.104.181.132:8888"},
            {"name": "📡 API Gateway", "url": "http://178.104.181.132:8700"},
        ]
    }


@app.get("/api/agents")
async def api_agents():
    """Coding agent status"""
    return {
        "agents": [
            {"name": "Claude Code", "emoji": "🔵", "status": "active", "provider": "MaxplusAI Proxy", "version": "2.1.126"},
            {"name": "OpenCode", "emoji": "🟢", "status": "active", "provider": "OpenRouter", "model": "nemotron-120b:free"},
            {"name": "thClaws", "emoji": "🦈", "status": "active", "provider": "OpenRouter", "version": "0.7.4", "model": "nemotron-9b:free"},
            {"name": "Nami Router", "emoji": "🧭", "status": "active", "version": "2.0"},
        ],
        "router": {
            "architecture": "deepseek→openrouter→nvidia→maxplus",
            "total_models": 371,
            "free_models": ["nemotron-120b", "nemotron-nano-9b", "nemotron-30b-reasoning"]
        }
    }


@app.get("/api/bridge")
async def api_bridge():
    """Nami Bridge status"""
    # Try connecting as agent
    bridge_status = "up"
    browser_status = "unknown"
    
    try:
        import websockets
        async with websockets.connect("ws://127.0.0.1:8888") as ws:
            await ws.send(json.dumps({"type": "hello", "role": "agent", "name": "API-Gateway"}))
            ack_raw = await asyncio.wait_for(ws.recv(), timeout=3)
            ack = json.loads(ack_raw)
            
            # Ping to check browser
            await ws.send(json.dumps({"type": "ping"}))
            try:
                pong_raw = await asyncio.wait_for(ws.recv(), timeout=3)
                pong = json.loads(pong_raw)
                browser_status = "connected" if pong.get("type") == "pong" else "error"
            except:
                browser_status = "disconnected"
    except:
        bridge_status = "down"
    
    return {
        "bridge": {
            "status": bridge_status,
            "port": 8888,
            "protocol": "websocket",
            "url": "ws://178.104.181.132:8888"
        },
        "browser": {
            "status": browser_status,
            "extension_version": "1.2.0",
            "install_url": "/nami-extension-v1.2.0.zip"
        }
    }


@app.get("/api/health")
async def api_health():
    """Simple health check"""
    return {"status": "ok", "service": "Nami API Gateway", "version": "1.0.0"}


@app.get("/api/backup")
async def api_backup():
    """Backup status — reads from backup_state.json"""
    state_file = Path("/opt/backup/backup_state.json")
    if state_file.exists():
        state = json.loads(state_file.read_text())
        return {
            "status": "ok",
            "last_backup": state.get("last_backup", "never"),
            "total_size_mb": state.get("total_size_mb", 0),
            "databases": state.get("databases", 0),
            "success_count": state.get("success_count", 0),
            "failed": state.get("failed", []),
            "kept_days": state.get("kept_days", 14),
            "disk_free_gb": state.get("disk_free_gb", 0),
        }
    return {"status": "unknown", "last_backup": "never"}


@app.get("/health")
async def health():
    """Health check (for load balancers)"""
    return {"status": "ok"}


# ─── Main ───────────────────────────────────────────────────────────

def main():
    import argparse
    parser = argparse.ArgumentParser(description="🌸 Nami API Gateway")
    parser.add_argument("--port", type=int, default=8700, help="Port (default: 8700)")
    parser.add_argument("--host", default="0.0.0.0", help="Host (default: 0.0.0.0)")
    args = parser.parse_args()
    
    print(f"🌸 Nami API Gateway v1.0.0")
    print(f"   http://{args.host}:{args.port}")
    print(f"   Docs: http://{args.host}:{args.port}/docs")
    
    uvicorn.run(app, host=args.host, port=args.port, log_level="info")


if __name__ == "__main__":
    main()
