#!/usr/bin/env bash
# ===========================================================================
#  TV-Wall - Selbsttest. Sammelt alles, was man zur Fehlersuche braucht.
#
#  Aufruf:  sudo /opt/tvwall/scripts/diagnose.sh
# ===========================================================================
set -uo pipefail

CONF="${1:-/etc/tvwall/tvwall.conf}"

hdr()  { printf '\n\033[1;36m── %s ─────────────────────────────────────\033[0m\n' "$*"; }
ok()   { printf '\033[1;32m  ✓\033[0m %s\n' "$*"; }
bad()  { printf '\033[1;31m  ✗\033[0m %s\n' "$*"; }
warn() { printf '\033[1;33m  !\033[0m %s\n' "$*"; }
note() { printf '    %s\n' "$*"; }

RUN_USER="tvwall"; DISPLAY_MODE="auto"; STATE_DIR="/var/lib/tvwall"; AP_SSID="?"
if [[ -f "$CONF" ]]; then
  set -a; . "$CONF" 2>/dev/null; set +a
fi
RUN_USER="${RUN_USER:-tvwall}"
DISPLAY_MODE="${DISPLAY_MODE:-auto}"
STATE_DIR="${STATE_DIR:-/var/lib/tvwall}"

hdr "System"
note "$(. /etc/os-release 2>/dev/null && echo "$PRETTY_NAME")"
note "Kernel: $(uname -srm)"
note "Modell: $(tr -d '\0' < /proc/device-tree/model 2>/dev/null || echo unbekannt)"
note "Standard-Ziel: $(systemctl get-default 2>/dev/null)"

hdr "Konfiguration ($CONF)"
if [[ -f "$CONF" ]]; then
  note "DISPLAY_MODE = $DISPLAY_MODE"
  note "RUN_USER     = $RUN_USER"
  note "STATE_DIR    = $STATE_DIR"
  note "AP_SSID      = ${AP_SSID:-?}"
else
  bad "Konfigurationsdatei fehlt"
fi

hdr "Programme"
for p in mpv ffmpeg nmcli; do
  if command -v "$p" >/dev/null; then ok "$p: $(command -v "$p")"; else bad "$p fehlt"; fi
done
if [[ -x /usr/local/bin/tvwall ]]; then
  ok "tvwall: $(/usr/local/bin/tvwall -version 2>/dev/null || echo vorhanden)"
else
  bad "/usr/local/bin/tvwall fehlt"
fi

hdr "Dienst"
if systemctl is-active --quiet tvwall; then ok "tvwall laeuft"; else bad "tvwall laeuft NICHT"; fi
if systemctl is-enabled --quiet tvwall 2>/dev/null; then ok "Autostart aktiv"; else warn "Autostart nicht aktiv"; fi
note "Unit-Benutzer: $(systemctl show -p User --value tvwall 2>/dev/null)"
note "Neustarts:     $(systemctl show -p NRestarts --value tvwall 2>/dev/null)"

hdr "Benutzer $RUN_USER"
if id "$RUN_USER" >/dev/null 2>&1; then
  ok "$(id "$RUN_USER")"
  for g in video render input; do
    id -nG "$RUN_USER" | tr ' ' '\n' | grep -qx "$g" \
      && ok "in Gruppe $g" || bad "NICHT in Gruppe $g"
  done
else
  bad "Benutzer existiert nicht"
fi

hdr "Bildschirm"
COMPOSITOR="$(pgrep -a -x 'labwc|wayfire|Xorg|Xwayland|weston|kwin_wayland' 2>/dev/null | head -3)"
if [[ -n "$COMPOSITOR" ]]; then
  warn "Es laeuft eine Desktop-Oberflaeche:"
  echo "$COMPOSITOR" | sed 's/^/      /'
  note "-> DISPLAY_MODE muss 'desktop' oder 'auto' sein, NICHT 'drm'."
else
  ok "keine Desktop-Oberflaeche aktiv (DRM/Konsole moeglich)"
fi

FOUND_SESSION=0
for d in /run/user/*; do
  [[ -d "$d" ]] || continue
  socks="$(ls "$d"/wayland-* 2>/dev/null | grep -v '\.lock$' | tr '\n' ' ')"
  [[ -z "$socks" ]] && continue
  FOUND_SESSION=1
  u="$(getent passwd "$(basename "$d")" | cut -d: -f1)"
  ok "Wayland-Sitzung von '$u': $socks"
  if [[ "$u" != "$RUN_USER" ]]; then
    bad "Der Dienst laeuft als '$RUN_USER', die Sitzung gehoert aber '$u'."
    note "-> In $CONF setzen:  RUN_USER=\"$u\"  und  DISPLAY_MODE=\"desktop\""
    note "-> danach:  sudo /opt/tvwall/install.sh --no-ap"
  fi
done
ls /tmp/.X11-unix/X* >/dev/null 2>&1 && { ok "X11-Sitzung vorhanden: $(ls /tmp/.X11-unix/)"; FOUND_SESSION=1; }
[[ $FOUND_SESSION -eq 0 ]] && note "keine Desktop-Sitzung gefunden"

for dev in /dev/dri/card*; do
  [[ -e "$dev" ]] && note "$(ls -l "$dev")"
done

hdr "Medien"
if [[ -d "$STATE_DIR/media" ]]; then
  COUNT="$(find "$STATE_DIR/media" -maxdepth 1 -type f | wc -l | tr -d ' ')"
  ok "$COUNT Datei(en) in $STATE_DIR/media"
  ls -lh "$STATE_DIR/media" 2>/dev/null | tail -n +2 | head -10 | sed 's/^/      /'
  [[ "$COUNT" == "0" ]] && warn "Ordner ist leer - dann bleibt der Bildschirm schwarz."
else
  bad "$STATE_DIR/media fehlt"
fi
[[ -f "$STATE_DIR/playlist.m3u" ]] && note "Playliste: $(($(wc -l < "$STATE_DIR/playlist.m3u") - 1)) Eintraege"

if command -v ffprobe >/dev/null; then
  echo
  note "Videodateien im Detail:"
  shopt -s nullglob nocaseglob
  for f in "$STATE_DIR"/media/*.{mp4,m4v,mov,mkv,avi,webm,mpg,mpeg,wmv,flv,ts,3gp,ogv}; do
    V="$(ffprobe -v error -select_streams v:0 \
         -show_entries stream=codec_name,width,height,avg_frame_rate \
         -of csv=p=0 "$f" 2>/dev/null)"
    D="$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$f" 2>/dev/null)"
    printf '      %-28s %s  %ss\n' "$(basename "$f")" "${V:-?}" "${D%%.*}"
    W="$(echo "$V" | cut -d, -f2)"
    C="$(echo "$V" | cut -d, -f1)"
    if [[ -n "$W" ]] && (( W > 1920 )); then
      warn "  ${W}px breit - fuer den Pi zu gross, bitte auf 1920 herunterrechnen"
    fi
    if [[ "$C" == "hevc" || "$C" == "h264" ]] && [[ "${MPV_HWDEC:-no}" != "no" ]]; then
      warn "  MPV_HWDEC=${MPV_HWDEC} - auf dem Pi 5 bleibt $C damit haengen."
      note "  -> MPV_HWDEC=\"no\" in $CONF setzen"
    fi
  done
  shopt -u nullglob nocaseglob
fi

hdr "Ton"
if command -v mpv >/dev/null && id "$RUN_USER" >/dev/null 2>&1; then
  RUN_UID="$(id -u "$RUN_USER")"
  DEVS="$(sudo -u "$RUN_USER" XDG_RUNTIME_DIR="/run/user/$RUN_UID" \
          timeout 10 mpv --audio-device=help 2>/dev/null | grep -v "^ *'auto'" | head -8)"
  if [[ -n "$DEVS" ]]; then
    ok "mpv sieht diese Audiogeraete:"
    echo "$DEVS" | sed 's/^/      /'
  else
    warn "mpv findet kein Audiogeraet - Videos mit Tonspur koennen dadurch haengen bleiben."
    note "-> In $CONF setzen:  AUDIO=\"no\""
  fi
  note "Aktuell eingestellt: AUDIO=${AUDIO:-yes}  MUTE=${MUTE:-no}"
fi

hdr "Webinterface"
PORT="${WEB_PORT:-80}"
CODE="$(curl -s -o /dev/null -w '%{http_code}' "http://127.0.0.1:$PORT/healthz" 2>/dev/null)"
if [[ "$CODE" == "200" ]]; then
  ok "erreichbar auf Port $PORT"
  curl -s "http://127.0.0.1:$PORT/api/state" 2>/dev/null \
    | tr ',' '\n' | grep -E '"(running|display|current|last_error)"' | sed 's/^/      /'
else
  bad "nicht erreichbar auf Port $PORT (HTTP $CODE)"
fi

hdr "Access Point"
if command -v nmcli >/dev/null; then
  nmcli -t -f NAME,DEVICE,STATE connection show --active 2>/dev/null | sed 's/^/      /'
  nmcli -t -f NAME connection show --active 2>/dev/null | grep -qx tvwall-ap \
    && ok "tvwall-ap aktiv" || warn "tvwall-ap nicht aktiv"
fi

hdr "Bildausgabe"
SWAP="$(journalctl -u tvwall --since "-30 min" --no-pager 2>/dev/null | grep -ci swapchain)"
if [[ "${SWAP:-0}" -gt 0 ]]; then
  bad "$SWAP Swapchain-Fehler in den letzten 30 Minuten"
  note "Die Vulkan-Anbindung von mpv laeuft auf dem Pi 5 nach wenigen"
  note "Bildwechseln aus dem Speicher: der Bildschirm friert ein, waehrend"
  note "das Webinterface weiterzaehlt."
  note "-> In $CONF setzen:  MPV_GPU_API=\"opengl\"  und Dienst neu starten"
else
  ok "keine Swapchain-Fehler (MPV_GPU_API=${MPV_GPU_API:-opengl})"
fi

hdr "Letzte Protokollzeilen"
journalctl -u tvwall -n 40 --no-pager 2>/dev/null | sed 's/^/  /'

hdr "Direkter mpv-Test"
FIRST="$(find "$STATE_DIR/media" -maxdepth 1 -type f 2>/dev/null | head -1)"
if [[ -n "$FIRST" ]]; then
  note "So laesst sich mpv unabhaengig vom Dienst pruefen:"
  note "  sudo systemctl stop tvwall"
  if [[ -n "$COMPOSITOR" ]]; then
    note "  sudo -u $RUN_USER XDG_RUNTIME_DIR=/run/user/\$(id -u $RUN_USER) mpv --fullscreen '$FIRST'"
  else
    note "  sudo -u $RUN_USER mpv --vo=gpu --gpu-context=drm --fullscreen '$FIRST'"
  fi
  note "  sudo systemctl start tvwall"
fi
echo
