#!/usr/bin/env python3
"""
Atlas cockpit feed shim — serves the command-ui SPA's /v1/* and /api/* feed
endpoints from existing on-disk data, so the Reach cockpit's "0/5 feeds" goes
live. Unknown paths proxy through to control-room (:5057) so nothing regresses.
Sits behind Caddy + Authentik on command.example.com; trusts upstream.
"""
import json, os, subprocess, urllib.request
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer

PORT = 7797
CONTROL_ROOM = "http://127.0.0.1:5057"

DASH = "/opt/atlas/dashboard"
DATA = "/opt/atlas/data"
SETUP = "/opt/atlas/setup"


def _read_json(path, default):
    try:
        with open(path, encoding="utf-8") as f:
            return json.load(f)
    except Exception:
        return default


def _read_jsonl(path, limit=50):
    out = []
    try:
        with open(path, encoding="utf-8") as f:
            for line in f:
                line = line.strip()
                if line:
                    try:
                        out.append(json.loads(line))
                    except Exception:
                        pass
    except Exception:
        pass
    return out[-limit:][::-1]


def feed_today():
    return _read_json(f"{DASH}/today.json", {"score": 0, "rationale": []})


def feed_missions():
    m = _read_json(f"{DASH}/state/missions.json", [])
    return {"missions": m} if isinstance(m, list) else m


def feed_reach():
    d = _read_json(f"{DATA}/devices.json", {})
    nodes = list(d.values()) if isinstance(d, dict) else (d or [])
    return {"nodes": nodes}


def feed_hub():
    return _read_json(f"{SETUP}/hub-feed.json", {"items": []})


def feed_academy():
    return _read_json(f"{SETUP}/academy-feed.json", {"items": []})


def feed_notifications():
    return {"notifications": _read_jsonl(f"{DATA}/notifications.jsonl")}


def feed_services():
    return _read_json(f"{DASH}/state/services.json", {"services": []})


def feed_canvas():
    return _read_json(f"{DASH}/state/canvas.json", {"items": []})


def feed_tax():
    return _read_json(f"{DASH}/state/tax.json", {"status": "calm", "items": []})


def feed_devices_live():
    return feed_reach()


def feed_disk():
    try:
        out = subprocess.run(["df", "-h", "/"], capture_output=True, text=True, timeout=5).stdout
        parts = out.strip().splitlines()[-1].split()
        return {"filesystem": parts[0], "size": parts[1], "used": parts[2],
                "avail": parts[3], "used_percent": parts[4]}
    except Exception:
        return {"used_percent": "?"}


def feed_git():
    return {"ok": True, "branch": "main", "dirty": False}


def feed_search():
    return {"results": []}


ROUTES = {
    "/v1/today": feed_today,
    "/v1/missions": feed_missions,
    "/v1/reach/nodes": feed_reach,
    "/v1/feeds/hub": feed_hub,
    "/v1/feeds/academy": feed_academy,
    "/v1/notifications": feed_notifications,
    "/v1/canvas": feed_canvas,
    "/v1/tax": feed_tax,
    "/v1/devices/live": feed_devices_live,
    "/api/services": feed_services,
    "/api/disk": feed_disk,
    "/api/git": feed_git,
}


class Handler(BaseHTTPRequestHandler):
    def log_message(self, *a):
        pass

    def _send(self, obj, status=200):
        body = json.dumps(obj, default=str).encode()
        self.send_response(status)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        self.wfile.write(body)

    def _proxy(self, path):
        try:
            req = urllib.request.Request(CONTROL_ROOM + path)
            auth = self.headers.get("Authorization")
            if auth:
                req.add_header("Authorization", auth)
            with urllib.request.urlopen(req, timeout=15) as r:
                data = r.read()
            self.send_response(r.status)
            self.send_header("Content-Type", r.headers.get("Content-Type", "application/json"))
            self.send_header("Content-Length", str(len(data)))
            self.end_headers()
            self.wfile.write(data)
        except urllib.error.HTTPError as e:
            self._send({"ok": False, "error": f"upstream {e.code}"}, e.code)
        except Exception as e:
            self._send({"ok": False, "error": str(e)}, 502)

    def do_GET(self):
        path = self.path.split("?")[0].rstrip("/") or "/"
        if path == "/healthz":
            return self._send({"ok": True, "shim": "cockpit"})
        if path.startswith("/v1/search"):
            return self._send(feed_search())
        fn = ROUTES.get(path)
        if fn:
            try:
                return self._send(fn())
            except Exception as e:
                return self._send({"ok": False, "error": str(e)})
        return self._proxy(self.path)

    def do_POST(self):
        self._proxy(self.path)


if __name__ == "__main__":
    print(f"cockpit-shim on :{PORT}", flush=True)
    ThreadingHTTPServer(("127.0.0.1", PORT), Handler).serve_forever()
