#!/usr/bin/env python3
"""
TAICOS PC Check - read-only diagnostic collector (Windows / Linux / macOS).
Run:  python3 taicos_pc_check.py
Prints a report you paste into TAICOS Software Fault mode.

READ-ONLY: changes nothing, writes nothing, makes no network calls.
Privacy: no hostnames, usernames, serials, IP or MAC addresses collected.
Works with the standard library alone; uses psutil / smartctl if present.
"""
import os, sys, platform, subprocess, shutil, datetime

L = []
def out(s=""): L.append(str(s))

def run(cmd, timeout=15):
    """Run a command, return stdout or '' - never raises."""
    try:
        p = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout)
        return (p.stdout or "").strip()
    except Exception:
        return ""

SYS = platform.system()
out("===== TAICOS PC CHECK =====")
out("Collected: " + datetime.datetime.now().strftime("%Y-%m-%d %H:%M"))
out("Platform : " + SYS + " " + platform.release())
out("")

out("--- SYSTEM ---")
out("OS        : " + platform.platform())
out("Machine   : " + platform.machine())
out("Python    : " + platform.python_version())
out("")

out("--- CPU ---")
out("Processor : " + (platform.processor() or "unknown"))
try:
    import psutil
    out("Cores     : %s physical / %s logical" % (psutil.cpu_count(False), psutil.cpu_count(True)))
    out("Load now  : %s %%" % psutil.cpu_percent(interval=1))
    f = psutil.cpu_freq()
    if f: out("Freq      : %.0f MHz (max %.0f)" % (f.current, f.max or 0))
except ImportError:
    if SYS == "Linux":
        m = [l for l in run(["lscpu"]).splitlines() if any(k in l for k in ("Model name","CPU(s):","MHz"))]
        for l in m[:6]: out("  " + l.strip())
    elif SYS == "Darwin":
        out("  " + run(["sysctl","-n","machdep.cpu.brand_string"]))
    out("  (install psutil for load/frequency detail:  pip install psutil)")
out("")

out("--- MEMORY ---")
try:
    import psutil
    v = psutil.virtual_memory()
    out("Total     : %.2f GB" % (v.total/1024**3))
    out("Available : %.2f GB" % (v.available/1024**3))
    out("Used      : %.1f %%" % v.percent)
    s = psutil.swap_memory()
    out("Swap      : %.2f GB total, %.1f%% used" % (s.total/1024**3, s.percent))
except ImportError:
    if SYS == "Linux":
        for l in open("/proc/meminfo").read().splitlines()[:5]: out("  " + l)
    elif SYS == "Darwin":
        b = run(["sysctl","-n","hw.memsize"])
        if b.isdigit(): out("Total     : %.2f GB" % (int(b)/1024**3))
out("")

out("--- STORAGE ---")
try:
    import psutil
    for p in psutil.disk_partitions(all=False):
        if any(x in (p.fstype or "") for x in ("tmpfs","overlay","squashfs","devtmpfs")):
            continue
        try:
            u = psutil.disk_usage(p.mountpoint)
            out("%-12s %s  %.1f GB total, %.1f GB free (%.1f%% used)" %
                (p.device, p.fstype, u.total/1024**3, u.free/1024**3, u.percent))
        except Exception:
            pass
except ImportError:
    if SYS in ("Linux","Darwin"):
        for l in run(["df","-h"]).splitlines():
            if l.startswith("Filesystem") or not any(x in l for x in ("tmpfs","overlay","squashfs","devtmpfs","udev")):
                out("  " + l)
out("")

out("--- DISK HEALTH (SMART) ---")
if shutil.which("smartctl"):
    devs = []
    if SYS == "Linux":
        devs = [("/dev/"+d) for d in os.listdir("/sys/block") if d.startswith(("sd","nvme","hd"))]
    elif SYS == "Darwin":
        devs = ["/dev/disk0"]
    elif SYS == "Windows":
        devs = ["/dev/sda"]
    for d in devs[:4]:
        r = run(["smartctl","-H","-A",d], timeout=25)
        if r:
            out("[%s]" % d)
            for line in r.splitlines():
                if any(k in line for k in ("Device Model","Model Number","overall-health","PASSED","FAILED",
                                           "Reallocated","Pending","Uncorrect","Power_On_Hours",
                                           "Temperature_Cel","Wear","Percentage Used","CRC_Error")):
                    out("  " + line.strip())
            out("")
        else:
            out("[%s] smartctl returned nothing (usually needs root/Administrator)" % d)
    out("NOTE: a SMART 'PASSED' verdict can still be a FAILING drive - the raw counters above")
    out("(Reallocated_Sector_Ct, Current_Pending_Sector, Offline_Uncorrectable) are what matter.")
else:
    out("smartctl not installed - this is the single most useful thing to add.")
    out("  Linux : sudo apt install smartmontools     then re-run with sudo")
    out("  macOS : brew install smartmontools")
    out("  Windows: install CrystalDiskInfo (free) and paste its report instead")
out("")

out("--- BATTERY ---")
try:
    import psutil
    b = psutil.sensors_battery()
    if b:
        out("Charge  : %s %%" % round(b.percent,1))
        out("Plugged : %s" % b.power_plugged)
    else:
        out("No battery detected (desktop).")
except Exception:
    if SYS == "Linux" and os.path.exists("/sys/class/power_supply/BAT0"):
        for k in ("capacity","status","cycle_count","energy_full","energy_full_design"):
            p = "/sys/class/power_supply/BAT0/" + k
            if os.path.exists(p):
                out("  %-18s %s" % (k, open(p).read().strip()))
    else:
        out("Battery info unavailable (install psutil for cross-platform detail).")
out("")

out("--- TEMPERATURES ---")
try:
    import psutil
    t = psutil.sensors_temperatures()
    if t:
        for name, arr in t.items():
            for e in arr[:3]:
                out("  %-18s %s  %.1f C" % (name, (e.label or ""), e.current))
    else:
        out("  No temperature sensors exposed.")
except Exception:
    out("  Temperature reading not available on this platform/build.")
out("")

out("--- RECENT SYSTEM ERRORS ---")
if SYS == "Linux":
    r = run(["journalctl","-p","3","-n","40","--no-pager"], timeout=20)
    if not r:
        r = run(["dmesg","--level=err,crit","-T"], timeout=20)
    out(r[-4000:] if r else "  No error log readable (try running with sudo).")
elif SYS == "Darwin":
    r = run(["log","show","--last","2d","--predicate",'messageType == 16 or messageType == 17',"--style","compact"], timeout=30)
    out(r[-4000:] if r else "  No errors returned.")
elif SYS == "Windows":
    r = run(["wevtutil","qe","System","/q:*[System[(Level=1 or Level=2)]]","/c:40","/f:text","/rd:true"], timeout=30)
    out(r[-4000:] if r else "  Could not read Event Log (try an Administrator prompt).")
out("")
out("===== END - copy everything above and paste into TAICOS Software Fault mode =====")

print("\n".join(L))
try:
    import subprocess as _s
    if SYS == "Darwin":
        _s.run(["pbcopy"], input="\n".join(L), text=True); print("\n[Copied to clipboard]")
    elif SYS == "Linux" and shutil.which("xclip"):
        _s.run(["xclip","-selection","clipboard"], input="\n".join(L), text=True); print("\n[Copied to clipboard]")
except Exception:
    pass
