#!/usr/bin/env python3
"""mdh-agent — streams machine and process metrics to your MDH dashboard.

Setup:
    pip install psutil requests
    python mdh_agent.py --api https://your-mdh-host --key mdk_live_xxx

Options:
    --interval 5          Seconds between metric posts (default: 5)
    --processes node,postgres   Only watch process names containing these
    --name my-macbook     Host display name (default: machine hostname)
"""
import argparse
import os
import platform
import socket
import sys
import time

try:
    import psutil
except ImportError:
    sys.exit("psutil is required: pip install psutil")
try:
    import requests
except ImportError:
    sys.exit("requests is required: pip install requests")


def discover_processes(watch):
    procs = []
    for p in psutil.process_iter(["pid", "name", "cpu_percent", "memory_info", "create_time", "cwd"]):
        try:
            info = p.info
            name = info["name"] or "?"
            if watch and not any(w.lower() in name.lower() for w in watch):
                continue
            kind = "process"
            display = name
            if "node" in name.lower() and info.get("cwd"):
                if os.path.exists(os.path.join(info["cwd"], "package.json")):
                    kind = "node-project"
                    display = f"node — {os.path.basename(info['cwd'])}"
            procs.append({
                "name": display,
                "kind": kind,
                "pid": info["pid"],
                "cpu": round(info["cpu_percent"] or 0.0, 1),
                "mem_mb": round((info["memory_info"].rss if info["memory_info"] else 0) / 1048576),
                "uptime_s": int(time.time() - (info["create_time"] or time.time())),
                "status": "ok",
            })
        except (psutil.NoSuchProcess, psutil.AccessDenied):
            continue
    procs.sort(key=lambda c: c["cpu"], reverse=True)
    return procs[:8]


def system_metrics():
    mem = psutil.virtual_memory()
    disk = psutil.disk_usage("/")
    return {
        "cpu": round(psutil.cpu_percent(interval=None), 1),
        "mem_pct": round(mem.percent, 1),
        "disk_pct": round(disk.percent, 1),
    }


def main():
    ap = argparse.ArgumentParser(description="MDH machine monitor agent")
    ap.add_argument("--api", required=True, help="MDH base URL, e.g. https://mdhapi.com")
    ap.add_argument("--key", required=True, help="API key with publish scope")
    ap.add_argument("--interval", type=float, default=5)
    ap.add_argument("--processes", default="")
    ap.add_argument("--name", default=socket.gethostname())
    args = ap.parse_args()

    api = args.api.rstrip("/")
    watch = [w.strip() for w in args.processes.split(",") if w.strip()]
    headers = {"X-Agent-Key": args.key, "Content-Type": "application/json"}

    r = requests.post(
        f"{api}/api/agent/register",
        json={"name": args.name, "platform": platform.platform()},
        headers=headers,
        timeout=30,
    )
    r.raise_for_status()
    host_id = r.json()["host_id"]
    print(f"[mdh-agent] registered as {host_id} ({args.name}) — streaming every {args.interval}s")

    psutil.cpu_percent(interval=None)  # prime the sampler
    for p in psutil.process_iter(["cpu_percent"]):
        try:
            p.cpu_percent()
        except Exception:
            pass

    while True:
        payload = {
            "host_id": host_id,
            "system": system_metrics(),
            "children": discover_processes(watch),
        }
        try:
            requests.post(
                f"{api}/api/agent/metrics", json=payload, headers=headers, timeout=30
            ).raise_for_status()
        except Exception as e:
            print(f"[mdh-agent] post failed: {e}")
        time.sleep(args.interval)


if __name__ == "__main__":
    main()
