#!/usr/bin/env python3
"""Telemetry ring-buffer snapshot — runs every 5min via cron.
Appends system metrics to telemetry_history.json (288 points = 24h).
"""
import json, os, time, subprocess
from datetime import datetime, timezone
from pathlib import Path

DATA_DIR = Path(__file__).parent / 'data'
HISTORY_FILE = DATA_DIR / 'telemetry_history.json'
STATE_FILE = DATA_DIR / 'telemetry_netstate.json'
MAX_POINTS = 288  # 24h @ 5min


def shell(cmd, timeout=5):
    try:
        r = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=timeout)
        return r.stdout.strip()
    except Exception:
        return ''


def gather():
    load = shell("cat /proc/loadavg | awk '{print $1}'")
    ncpu = shell("nproc")
    try:
        cpu = round(min(float(load) / max(int(ncpu), 1) * 100, 100), 1)
    except Exception:
        cpu = 0

    mem = shell("free | awk '/Mem:/{printf \"%.1f\", $3/$2*100}'")
    try:
        mem = float(mem)
    except Exception:
        mem = 0

    net_raw = shell("cat /proc/net/dev | awk '/eth0|ens|enp/{print $2,$10; exit}'")
    parts = net_raw.split()
    rx = int(parts[0]) if len(parts) >= 2 else 0
    tx = int(parts[1]) if len(parts) >= 2 else 0

    # Rate calc from previous state
    prev = {}
    if STATE_FILE.exists():
        try:
            prev = json.loads(STATE_FILE.read_text())
        except Exception:
            prev = {}

    now = time.time()
    rx_bps = tx_bps = 0
    if prev.get('ts') and now > prev['ts']:
        dt = now - prev['ts']
        rx_bps = max(0, int((rx - prev.get('rx', 0)) / dt))
        tx_bps = max(0, int((tx - prev.get('tx', 0)) / dt))

    STATE_FILE.write_text(json.dumps({'rx': rx, 'tx': tx, 'ts': now}))

    return {
        'cpu': cpu,
        'mem': mem,
        'net_rx': rx_bps,
        'net_tx': tx_bps,
        'ts': datetime.now(timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ'),
    }


def append_history(point):
    data = {'cpu': [], 'mem': [], 'net_rx': [], 'net_tx': [], 'timestamps': []}
    if HISTORY_FILE.exists():
        try:
            data = json.loads(HISTORY_FILE.read_text())
            # Ensure all keys exist
            for k in ('cpu', 'mem', 'net_rx', 'net_tx', 'timestamps'):
                data.setdefault(k, [])
        except Exception:
            pass

    data['cpu'].append(point['cpu'])
    data['mem'].append(point['mem'])
    data['net_rx'].append(point['net_rx'])
    data['net_tx'].append(point['net_tx'])
    data['timestamps'].append(point['ts'])

    # Ring buffer trim
    for k in ('cpu', 'mem', 'net_rx', 'net_tx', 'timestamps'):
        if len(data[k]) > MAX_POINTS:
            data[k] = data[k][-MAX_POINTS:]

    DATA_DIR.mkdir(parents=True, exist_ok=True)
    HISTORY_FILE.write_text(json.dumps(data))


if __name__ == '__main__':
    try:
        point = gather()
        append_history(point)
        print(f"[{point['ts']}] cpu={point['cpu']}% mem={point['mem']}% rx={point['net_rx']}bps tx={point['net_tx']}bps")
    except Exception as e:
        print(f"[ERROR] {e}")
        raise
