#!/usr/bin/env python3
"""
sysmon - System monitor

Quick system status and resource tracking.
"""

import os
import json
import subprocess
from datetime import datetime
from pathlib import Path

WORKSPACE = Path("/home/wdjones/.openclaw/workspace")
HISTORY_FILE = WORKSPACE / "data" / "sysmon_history.json"

def get_cpu_usage():
    """Get CPU usage percentage."""
    try:
        # Read /proc/stat for CPU usage
        with open('/proc/stat') as f:
            line = f.readline()
        parts = line.split()
        idle = int(parts[4])
        total = sum(int(p) for p in parts[1:])
        
        # Read again after a moment
        import time
        time.sleep(0.1)
        
        with open('/proc/stat') as f:
            line = f.readline()
        parts = line.split()
        idle2 = int(parts[4])
        total2 = sum(int(p) for p in parts[1:])
        
        idle_delta = idle2 - idle
        total_delta = total2 - total
        
        if total_delta == 0:
            return 0
        
        usage = 100 * (1 - idle_delta / total_delta)
        return round(usage, 1)
    except:
        return None

def get_memory():
    """Get memory usage."""
    try:
        with open('/proc/meminfo') as f:
            lines = f.readlines()
        
        mem = {}
        for line in lines:
            parts = line.split()
            key = parts[0].rstrip(':')
            value = int(parts[1])  # in KB
            mem[key] = value
        
        total = mem.get('MemTotal', 0) / 1024 / 1024  # GB
        available = mem.get('MemAvailable', 0) / 1024 / 1024  # GB
        used = total - available
        pct = (used / total * 100) if total > 0 else 0
        
        return {
            'total_gb': round(total, 1),
            'used_gb': round(used, 1),
            'available_gb': round(available, 1),
            'percent': round(pct, 1),
        }
    except:
        return None

def get_disk():
    """Get disk usage."""
    try:
        stat = os.statvfs('/')
        total = stat.f_blocks * stat.f_frsize / 1024 / 1024 / 1024  # GB
        free = stat.f_bavail * stat.f_frsize / 1024 / 1024 / 1024  # GB
        used = total - free
        pct = (used / total * 100) if total > 0 else 0
        
        return {
            'total_gb': round(total, 1),
            'used_gb': round(used, 1),
            'free_gb': round(free, 1),
            'percent': round(pct, 1),
        }
    except:
        return None

def get_load():
    """Get system load average."""
    try:
        with open('/proc/loadavg') as f:
            parts = f.read().split()
        return {
            'load1': float(parts[0]),
            'load5': float(parts[1]),
            'load15': float(parts[2]),
        }
    except:
        return None

def get_uptime():
    """Get system uptime."""
    try:
        with open('/proc/uptime') as f:
            uptime_seconds = float(f.read().split()[0])
        
        days = int(uptime_seconds // 86400)
        hours = int((uptime_seconds % 86400) // 3600)
        mins = int((uptime_seconds % 3600) // 60)
        
        if days > 0:
            return f"{days}d {hours}h {mins}m"
        elif hours > 0:
            return f"{hours}h {mins}m"
        else:
            return f"{mins}m"
    except:
        return None

def get_processes():
    """Get top processes by memory/CPU."""
    try:
        result = subprocess.run(
            ['ps', 'aux', '--sort=-rss'],
            capture_output=True, text=True
        )
        lines = result.stdout.strip().split('\n')[1:6]  # Skip header, top 5
        
        processes = []
        for line in lines:
            parts = line.split(None, 10)
            if len(parts) >= 11:
                processes.append({
                    'user': parts[0],
                    'cpu': float(parts[2]),
                    'mem': float(parts[3]),
                    'cmd': parts[10][:30],
                })
        return processes
    except:
        return []

def bar(pct: float, width: int = 20) -> str:
    """Create a progress bar."""
    filled = int(pct / 100 * width)
    return "█" * filled + "░" * (width - filled)

def show_status():
    """Show current system status."""
    print()
    print("╔" + "═" * 40 + "╗")
    print(f"║  🖥️  System Monitor {' ' * 20}║")
    print("╚" + "═" * 40 + "╝")
    
    # Uptime
    uptime = get_uptime()
    if uptime:
        print(f"\n⏰ Uptime: {uptime}")
    
    # CPU
    cpu = get_cpu_usage()
    if cpu is not None:
        print(f"\n🔲 CPU:    {bar(cpu)} {cpu}%")
    
    # Memory
    mem = get_memory()
    if mem:
        print(f"🔲 Memory: {bar(mem['percent'])} {mem['percent']}%")
        print(f"          {mem['used_gb']:.1f}GB / {mem['total_gb']:.1f}GB")
    
    # Disk
    disk = get_disk()
    if disk:
        print(f"🔲 Disk:   {bar(disk['percent'])} {disk['percent']}%")
        print(f"          {disk['used_gb']:.0f}GB / {disk['total_gb']:.0f}GB")
    
    # Load
    load = get_load()
    if load:
        print(f"\n📊 Load: {load['load1']:.2f} / {load['load5']:.2f} / {load['load15']:.2f}")
    
    # Top processes
    procs = get_processes()
    if procs:
        print(f"\n🔝 Top Processes:")
        for p in procs[:3]:
            print(f"   {p['mem']:.1f}% {p['cmd']}")
    
    print()

def record():
    """Record current stats to history."""
    HISTORY_FILE.parent.mkdir(parents=True, exist_ok=True)
    
    if HISTORY_FILE.exists():
        with open(HISTORY_FILE) as f:
            history = json.load(f)
    else:
        history = []
    
    entry = {
        'timestamp': datetime.now().isoformat(),
        'cpu': get_cpu_usage(),
        'memory': get_memory(),
        'disk': get_disk(),
        'load': get_load(),
    }
    
    history.append(entry)
    
    # Keep last 1000 entries
    history = history[-1000:]
    
    with open(HISTORY_FILE, 'w') as f:
        json.dump(history, f)
    
    print(f"✓ Recorded at {entry['timestamp'][:19]}")

def main():
    import sys
    
    if len(sys.argv) > 1:
        cmd = sys.argv[1]
        if cmd == 'record':
            record()
        else:
            print("Usage: sysmon [record]")
    else:
        show_status()

if __name__ == "__main__":
    main()
