#!/usr/bin/env python3
"""Split-brain worker 1: connectivity watchdog.
Checks the Pi -> Dex VM path (Tailscale) and home egress every run,
writes a JSON result. Dex (the brain) collects results over SSH.
Read-only w.r.t. the network: ping, tailscale status, one HTTPS HEAD.
"""
import json, subprocess, time, os, glob
from datetime import datetime, timezone

DEX = "/home/div/dex"
RUNS = DEX + "/runs"
NOW = datetime.now(timezone.utc)

def run(cmd, timeout=15):
    try:
        p = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout)
        return p.returncode, p.stdout.strip(), p.stderr.strip()[:200]
    except subprocess.TimeoutExpired:
        return -1, "", "timeout"
    except Exception as e:
        return -1, "", str(e)[:200]

result = {"ts": NOW.isoformat(), "job": "net-watch"}

# 1. ICMP ping to Dex VM over Tailscale
rc, out, _ = run(["ping", "-c3", "-W2", "100.91.196.120"])
result["vm_ping_ok"] = (rc == 0)
lat = None
for line in out.splitlines():
    if "rtt min/avg/max" in line:
        try:
            lat = float(line.split("=")[1].split("/")[1])
        except Exception:
            pass
result["vm_ping_latency_ms"] = lat

# 2. Which relay the VM peer is on (informational)
rc, out, _ = run(["tailscale", "status"])
relay = None
for line in out.splitlines():
    if "100.91.196.120" in line:
        if 'relay "' in line:
            relay = line.split('relay "')[1].split('"')[0]
        elif "direct" in line:
            relay = "direct"
result["vm_relay"] = relay

# 3. Home egress check (single lightweight HTTPS request)
rc, out, _ = run(["curl", "-s", "-o", "/dev/null", "-w", "%{http_code}",
                  "--max-time", "10", "https://www.google.com"])
result["egress_ok"] = (out == "200")
result["egress_code"] = out

os.makedirs(RUNS, exist_ok=True)
fname = RUNS + "/net-watch-" + NOW.strftime("%Y%m%d-%H%M%S") + ".json"
with open(fname, "w") as f:
    json.dump(result, f)

# prune runs older than 24h
cutoff = time.time() - 86400
for p in glob.glob(RUNS + "/net-watch-*.json"):
    try:
        if os.path.getmtime(p) < cutoff:
            os.remove(p)
    except OSError:
        pass

with open(DEX + "/logs/net-watch.log", "a") as f:
    f.write("%s vm_ping_ok=%s lat=%s relay=%s egress_ok=%s\n" % (
        result["ts"], result["vm_ping_ok"], lat, relay, result["egress_ok"]))
