#!/usr/bin/env python3
"""
服务器哨兵 · Server Sentinel · ICE-GL-ZY-AGT-SENTINEL-003

铸渊需要知道哪台服务器在线、哪台可用？
哨兵一键扫描全部12台。

用法:
  python3 sentinel.py scan                  # 扫描全部服务器
  python3 sentinel.py status BS-SG-001      # 单台服务器详情
  python3 sentinel.py ready                  # 找一台可用服务器
"""

import json
import os
import sys
import urllib.request
from pathlib import Path

REPO_ROOT = Path(__file__).resolve().parent.parent.parent

def load_gatekeepers():
    gk_path = REPO_ROOT / "brain" / "gatekeeper-deployment.json"
    if gk_path.exists():
        with open(gk_path) as f:
            return json.load(f)
    return {"servers": []}

def check_server(server):
    """检查单台服务器"""
    url = f"http://{server['ip']}:{server['port']}/exec"
    data = json.dumps({"cmd": "echo ONLINE && hostname && free -h | grep Mem | awk '{print $2,$3,$4}' && df -h / | tail -1 | awk '{print $2,$3,$4}'"}).encode()
    try:
        req = urllib.request.Request(
            url, data=data,
            headers={
                "Authorization": f"Bearer {server['key']}",
                "Content-Type": "application/json"
            }
        )
        with urllib.request.urlopen(req, timeout=10) as resp:
            result = json.loads(resp.read())

        if result.get("ok"):
            lines = result.get("stdout", "").strip().split("\n")
            return {
                "code": server["code"],
                "name": server.get("name", ""),
                "online": True,
                "hostname": lines[0] if len(lines) > 0 else "?",
                "memory": lines[1] if len(lines) > 1 else "?",
                "disk": lines[2] if len(lines) > 2 else "?",
            }
        return {"code": server["code"], "online": False, "error": result.get("stderr", "")}
    except Exception as e:
        return {"code": server["code"], "online": False, "error": str(e)[:100]}

def scan_all():
    """扫描全部服务器"""
    data = load_gatekeepers()
    results = []
    online_count = 0

    for s in data.get("servers", []):
        r = check_server(s)
        results.append(r)
        if r.get("online"):
            online_count += 0

    # 按域分组
    by_domain = {}
    for r in results:
        srv = next((x for x in data["servers"] if x["code"] == r["code"]), {})
        domain = srv.get("domain", "unknown")
        if domain not in by_domain:
            by_domain[domain] = []
        by_domain[domain].append(r)

    return {
        "total": len(results),
        "online": online_count,
        "by_domain": by_domain,
        "servers": results
    }

def find_available():
    """找一台可用服务器"""
    data = load_gatekeepers()
    # 优先ice-core域
    for s in data.get("servers", []):
        if s.get("domain") == "ice-core":
            r = check_server(s)
            if r.get("online"):
                return {"found": True, "server": r, "note": "ice-core域优先"}
    # 其他域
    for s in data.get("servers", []):
        if s.get("domain") != "ice-core":
            r = check_server(s)
            if r.get("online"):
                return {"found": True, "server": r}
    return {"found": False, "note": "所有服务器不可达"}

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("用法: sentinel.py <scan|status|ready>")
        sys.exit(1)

    action = sys.argv[1]

    if action == "scan":
        print(json.dumps(scan_all(), ensure_ascii=False, indent=2))
    elif action == "status" and len(sys.argv) > 2:
        data = load_gatekeepers()
        for s in data["servers"]:
            if s["code"] == sys.argv[2]:
                print(json.dumps(check_server(s), ensure_ascii=False, indent=2))
                break
    elif action == "ready":
        print(json.dumps(find_available(), ensure_ascii=False, indent=2))
