#!/usr/bin/env bash
# TerraSolution System-Check für Proxmox VE 9.x
# Nur lesende Diagnose. Keine Konfigurationsänderungen.
set -u

CHECKS_FILE="$(mktemp)"
trap 'rm -f "$CHECKS_FILE"' EXIT

json_escape() {
  python3 -c 'import json,sys; print(json.dumps(sys.stdin.read()))'
}

add_check() {
  local category="$1" status="$2" message="$3" details="${4:-}"
  printf '%s\t%s\t%s\t%s\n' "$category" "$status" "$message" "$details" >> "$CHECKS_FILE"
}

HOST="$(hostname)"
PVE="$(pveversion 2>/dev/null | head -n1 || true)"
[[ -z "$PVE" ]] && PVE="Linux/Proxmox unbekannt"

# Root filesystem
ROOT_PCT="$(df -P / | awk 'NR==2 {gsub("%","",$5); print $5}')"
if [[ "${ROOT_PCT:-0}" -ge 90 ]]; then
  add_check "Storage" "red" "Root-Dateisystem ${ROOT_PCT}% belegt" "$(df -hT /)"
elif [[ "${ROOT_PCT:-0}" -ge 80 ]]; then
  add_check "Storage" "yellow" "Root-Dateisystem ${ROOT_PCT}% belegt" "$(df -hT /)"
else
  add_check "Storage" "green" "Root-Dateisystem ${ROOT_PCT}% belegt" "$(df -hT /)"
fi

# Inodes
INO_PCT="$(df -Pi / | awk 'NR==2 {gsub("%","",$5); print $5}')"
if [[ "${INO_PCT:-0}" -ge 90 ]]; then
  add_check "Inodes" "red" "Root-Inodes ${INO_PCT}% belegt" "$(df -ih /)"
elif [[ "${INO_PCT:-0}" -ge 80 ]]; then
  add_check "Inodes" "yellow" "Root-Inodes ${INO_PCT}% belegt" "$(df -ih /)"
else
  add_check "Inodes" "green" "Root-Inodes ${INO_PCT}% belegt" "$(df -ih /)"
fi

# Failed services
FAILED="$(systemctl --failed --no-legend 2>/dev/null | sed '/^[[:space:]]*$/d' || true)"
FAILED_COUNT="$(printf '%s\n' "$FAILED" | sed '/^[[:space:]]*$/d' | wc -l)"
if [[ "$FAILED_COUNT" -gt 0 ]]; then
  add_check "Dienste" "red" "$FAILED_COUNT fehlgeschlagene systemd Unit(s)" "$FAILED"
else
  add_check "Dienste" "green" "Keine fehlgeschlagenen systemd Units"
fi

# Proxmox storage
PVE_STORAGE="$(pvesm status 2>&1 || true)"
if printf '%s' "$PVE_STORAGE" | grep -qiE 'inactive|unknown|error'; then
  add_check "Proxmox Storage" "red" "Mindestens ein Storage ist auffällig" "$PVE_STORAGE"
else
  add_check "Proxmox Storage" "green" "Proxmox Storage-Status ohne offensichtliche Fehler" "$PVE_STORAGE"
fi

# ZFS
if command -v zpool >/dev/null 2>&1 && zpool list >/dev/null 2>&1; then
  ZSTAT="$(zpool status -v 2>&1)"
  if printf '%s' "$ZSTAT" | grep -qE 'DEGRADED|FAULTED|UNAVAIL|OFFLINE|REMOVED'; then
    add_check "ZFS" "red" "ZFS-Pool nicht vollständig ONLINE" "$ZSTAT"
  elif printf '%s' "$ZSTAT" | grep -q 'errors: No known data errors'; then
    add_check "ZFS" "green" "ZFS-Poolstatus unauffällig" "$ZSTAT"
  else
    add_check "ZFS" "yellow" "ZFS-Poolstatus manuell prüfen" "$ZSTAT"
  fi
fi

# SMART
if command -v smartctl >/dev/null 2>&1; then
  BADSMART=""
  SMARTDETAIL=""
  while read -r dev; do
    [[ -z "$dev" ]] && continue
    out="$(smartctl -H "$dev" 2>&1 || true)"
    SMARTDETAIL+=$'\n'"=== $dev ==="$'\n'"$out"
    if ! printf '%s' "$out" | grep -qiE 'PASSED|OK'; then
      BADSMART+="$dev "
    fi
  done < <(smartctl --scan-open 2>/dev/null | awk '{print $1}')
  if [[ -n "$BADSMART" ]]; then
    add_check "SMART" "red" "SMART-Status auffällig: $BADSMART" "$SMARTDETAIL"
  else
    add_check "SMART" "green" "SMART Health ohne offensichtlichen Fehler" "$SMARTDETAIL"
  fi
else
  add_check "SMART" "yellow" "smartctl nicht installiert" "smartmontools installieren/Herstellerdiagnose verwenden, falls SMART-Prüfung gewünscht."
fi

# Journal errors
JERR="$(journalctl -p err..alert --since '7 days ago' --no-pager 2>/dev/null | tail -n 200 || true)"
JCOUNT="$(printf '%s\n' "$JERR" | sed '/^[[:space:]]*$/d' | wc -l)"
if [[ "$JCOUNT" -gt 50 ]]; then
  add_check "Journal" "red" "$JCOUNT Fehlerzeilen in 7 Tagen" "$JERR"
elif [[ "$JCOUNT" -gt 0 ]]; then
  add_check "Journal" "yellow" "$JCOUNT Fehlerzeilen in 7 Tagen" "$JERR"
else
  add_check "Journal" "green" "Keine Journal-Fehlerzeilen in 7 Tagen"
fi

# Backup local
if [[ -d /var/lib/vz/dump ]]; then
  RECENT="$(find /var/lib/vz/dump -maxdepth 1 -type f -mtime -7 -printf '%TY-%Tm-%Td %TH:%TM %f\n' 2>/dev/null | sort -r | head -n 30)"
  if [[ -n "$RECENT" ]]; then
    add_check "Backup" "green" "Lokale Backup-Datei(en) der letzten 7 Tage gefunden" "$RECENT"
  else
    add_check "Backup" "yellow" "Keine lokale Backup-Datei der letzten 7 Tage gefunden" "Bei PBS/NFS/CIFS kann dies normal sein; externes Ziel zusätzlich prüfen."
  fi
else
  add_check "Backup" "yellow" "Lokales Dump-Verzeichnis nicht vorhanden" "Externe Backupziele/PBS prüfen."
fi

# Task errors
TASKERR="$(grep -R 'TASK ERROR' /var/log/pve/tasks/ 2>/dev/null | tail -n 30 || true)"
if [[ -n "$TASKERR" ]]; then
  add_check "Proxmox Tasks" "yellow" "TASK ERROR Einträge gefunden" "$TASKERR"
else
  add_check "Proxmox Tasks" "green" "Keine aktuellen TASK ERROR Treffer in Tasklogs"
fi

# Updates
UPDATES="$(apt list --upgradable 2>/dev/null | tail -n +2 | sed '/^[[:space:]]*$/d' || true)"
UCOUNT="$(printf '%s\n' "$UPDATES" | sed '/^[[:space:]]*$/d' | wc -l)"
if [[ "$UCOUNT" -gt 0 ]]; then
  add_check "Updates" "yellow" "$UCOUNT Paketupdate(s) verfügbar" "$(printf '%s\n' "$UPDATES" | head -n 50)"
else
  add_check "Updates" "green" "Keine verfügbaren Paketupdates gemeldet"
fi

# Reboot
if [[ -f /var/run/reboot-required ]]; then
  add_check "Neustart" "yellow" "Neustart angefordert" "$(cat /var/run/reboot-required 2>/dev/null)"
else
  add_check "Neustart" "green" "Kein reboot-required Indikator"
fi

# Cluster
if command -v pvecm >/dev/null 2>&1; then
  CLUSTER="$(pvecm status 2>&1 || true)"
  if printf '%s' "$CLUSTER" | grep -qi 'Quorate:[[:space:]]*Yes'; then
    add_check "Cluster" "green" "Cluster ist quorate" "$CLUSTER"
  elif printf '%s' "$CLUSTER" | grep -qiE 'not initialized|Cannot initialize CMAP|no cluster'; then
    add_check "Cluster" "green" "Standalone-Node / kein Cluster erkannt"
  else
    add_check "Cluster" "yellow" "Clusterstatus manuell prüfen" "$CLUSTER"
  fi
fi

# Determine worst
OVERALL="green"
if awk -F '\t' '$2=="red"{found=1} END{exit !found}' "$CHECKS_FILE"; then
  OVERALL="red"
elif awk -F '\t' '$2=="yellow"{found=1} END{exit !found}' "$CHECKS_FILE"; then
  OVERALL="yellow"
fi

if [[ "$OVERALL" == "red" ]]; then
  SUMMARY="Mindestens eine kritische Auffälligkeit erkannt. Einzelbefunde prüfen."
elif [[ "$OVERALL" == "yellow" ]]; then
  SUMMARY="Keine rote Auffälligkeit, aber mindestens ein Punkt sollte geprüft/beobachtet werden."
else
  SUMMARY="Automatischer System-Check ohne erkennbare rote/gelbe Auffälligkeit."
fi

OUTDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
OUTFILE="$OUTDIR/TerraSolution-SystemCheck-${HOST}-$(date +%Y%m%d-%H%M%S).json"

python3 - "$CHECKS_FILE" "$OUTFILE" "$HOST" "$PVE" "$OVERALL" "$SUMMARY" <<'PY'
import json,sys,datetime
checks_file,outfile,host,platform,overall,summary=sys.argv[1:]
checks=[]
with open(checks_file,encoding='utf-8',errors='replace') as f:
    for line in f:
        parts=line.rstrip('\n').split('\t',3)
        while len(parts)<4: parts.append('')
        checks.append({"category":parts[0],"status":parts[1],"message":parts[2],"details":parts[3]})
report={
    "schema":"TerraSolution-SystemCheck-v1",
    "generatedAt":datetime.datetime.now(datetime.timezone.utc).astimezone().isoformat(),
    "hostname":host,
    "platform":platform,
    "overall":overall,
    "summary":summary,
    "checks":checks
}
with open(outfile,'w',encoding='utf-8') as f:
    json.dump(report,f,ensure_ascii=False,indent=2)
PY

echo
echo "========================================================="
echo " TerraSolution Proxmox System-Check"
echo "========================================================="
echo "Host    : $HOST"
echo "Version : $PVE"
echo "Gesamt  : ${OVERALL^^}"
echo
while IFS=$'\t' read -r cat status msg details; do
  case "$status" in
    green) icon="[GRUEN]" ;;
    yellow) icon="[GELB]" ;;
    red) icon="[ROT]" ;;
    *) icon="[?]" ;;
  esac
  echo "$icon $cat: $msg"
done < "$CHECKS_FILE"
echo
echo "JSON-Bericht: $OUTFILE"
echo "Diese Datei im TerraSolution Wartungsportal unter 'System-Check / Ampel' importieren."
