#!/usr/bin/env bash
set -u

PLUGIN_ID="local.omarchy-citizen"
PLUGIN_VERSION="0.8.0"

CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/starcitizen-lug"
DATA_DIR="${XDG_DATA_HOME:-$HOME/.local/share}"
CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/omarchy-citizen"
STATE_DIR="${XDG_STATE_HOME:-$HOME/.local/state}/omarchy-citizen"
UPDATE_CACHE="$CACHE_DIR/lug-update-status"
LOG_FILE="$STATE_DIR/omarchy-citizen.log"
WINE_CONF="$CONFIG_DIR/winedir.conf"
GAME_CONF="$CONFIG_DIR/gamedir.conf"
SELF="$(readlink -f "${BASH_SOURCE[0]}")"
PLUGIN_DIR="$(cd -- "$(dirname -- "$SELF")" && pwd)"
SANITIZER="$PLUGIN_DIR/support-sanitize.py"
BACKEND_EXTERNAL="$HOME/.local/lib/omarchy-citizen/omarchy-citizen-backend"
BACKEND_BUNDLED="$PLUGIN_DIR/backend/bin/omarchy-citizen-backend"
MANAGED_LUG="$DATA_DIR/omarchy-citizen/vendor/lug-helper/lug-helper.appimage"
MANAGED_WINE="$DATA_DIR/omarchy-citizen/vendor/wine/current"

GUI_PACKAGES=(zenity polkit cabextract unzip)

mkdir -p "$CACHE_DIR" "$STATE_DIR"

rotate_log() {
  local max_bytes=$((4 * 1024 * 1024))
  local keep_bytes=$((2 * 1024 * 1024))
  if [[ -f "$LOG_FILE" ]] && (( $(stat -c '%s' "$LOG_FILE" 2>/dev/null || echo 0) > max_bytes )); then
    tail -c "$keep_bytes" "$LOG_FILE" > "$LOG_FILE.tmp" 2>/dev/null || true
    mv -f "$LOG_FILE.tmp" "$LOG_FILE" 2>/dev/null || true
  fi
}

rotate_log

ACTION="${1:-primary}"

log_line() {
  local message="$*"
  printf '%s [%s] %s\n' "$(date '+%Y-%m-%dT%H:%M:%S%z')" "$$" "$message" >> "$LOG_FILE" 2>/dev/null || true
}

log_line "action=$ACTION version=$PLUGIN_VERSION"


find_backend() {
  if [[ -x "$BACKEND_EXTERNAL" ]]; then
    printf '%s\n' "$BACKEND_EXTERNAL"
    return 0
  fi
  if [[ -x "$BACKEND_BUNDLED" ]]; then
    printf '%s\n' "$BACKEND_BUNDLED"
    return 0
  fi
  return 1
}

backend_status() {
  local game_output="" plugin_output="" health="setup" prefix_state="missing" launcher_state="missing" game_state="missing"
  local wine_version="" dxvk_version="" lug_version="" hardware="unknown" hardware_reason="" gpu="" vulkan="unknown"

  if game_output="$(backend_game_status 2>/dev/null)"; then
    health="$(printf '%s\n' "$game_output" | sed -n 's/^health=//p' | head -n1)"
    prefix_state="$(printf '%s\n' "$game_output" | sed -n 's/^prefix_state=//p' | head -n1)"
    launcher_state="$(printf '%s\n' "$game_output" | sed -n 's/^launcher_state=//p' | head -n1)"
    game_state="$(printf '%s\n' "$game_output" | sed -n 's/^game_state=//p' | head -n1)"
    wine_version="$(printf '%s\n' "$game_output" | sed -n 's/^wine_version=//p' | head -n1)"
    dxvk_version="$(printf '%s\n' "$game_output" | sed -n 's/^dxvk_version=//p' | head -n1)"
    lug_version="$(printf '%s\n' "$game_output" | sed -n 's/^lug_version=//p' | head -n1)"
    hardware="$(printf '%s\n' "$game_output" | sed -n 's/^hardware=//p' | head -n1)"
    hardware_reason="$(printf '%s\n' "$game_output" | sed -n 's/^hardware_reason=//p' | head -n1)"
    gpu="$(printf '%s\n' "$game_output" | sed -n 's/^gpu=//p' | head -n1)"
    vulkan="$(printf '%s\n' "$game_output" | sed -n 's/^vulkan=//p' | head -n1)"
  fi

  printf 'plugin_version=%s\n' "$PLUGIN_VERSION"
  printf 'health=%s\n' "${health:-setup}"
  printf 'deps=ready\n'
  printf 'deps_missing=\n'
  printf 'helper=%s\n' "$([[ -n "$lug_version" ]] && echo ready || echo missing)"
  printf 'helper_managed=autopilot\n'
  printf 'helper_version=%s\n' "$lug_version"
  printf 'update=unknown\n'
  printf 'update_version=\n'
  printf 'prefix=%s\n' "${prefix_state:-missing}"
  if [[ "$prefix_state" == "partial" ]]; then printf 'prefix_detail=unvollständig\n'; else printf 'prefix_detail=\n'; fi
  printf 'launcher=%s\n' "${launcher_state:-missing}"
  printf 'game=%s\n' "${game_state:-missing}"
  printf 'hardware=%s\n' "$hardware"
  printf 'hardware_reason=%s\n' "$hardware_reason"
  printf 'hardware_gpu=%s\n' "$gpu"
  printf 'hardware_vulkan=%s\n' "$vulkan"

  if plugin_output="$(backend_status 2>/dev/null)"; then
    printf 'backend=ready\n'
  else
    printf 'backend=missing\n'
  fi
  printf 'backend_version=%s\n' "$(printf '%s\n' "$plugin_output" | sed -n 's/^backend_version=//p' | head -n1)"
  printf 'plugin_managed=%s\n' "$(printf '%s\n' "$plugin_output" | sed -n 's/^managed=//p' | head -n1)"
  printf 'plugin_auto=%s\n' "$(printf '%s\n' "$plugin_output" | sed -n 's/^auto_apply=//p' | head -n1)"
  printf 'plugin_update=%s\n' "$(printf '%s\n' "$plugin_output" | sed -n 's/^update=//p' | head -n1)"
  printf 'plugin_local_commit=%s\n' "$(printf '%s\n' "$plugin_output" | sed -n 's/^local_commit=//p' | head -n1)"
  printf 'plugin_remote_commit=%s\n' "$(printf '%s\n' "$plugin_output" | sed -n 's/^remote_commit=//p' | head -n1)"
  printf 'autopilot=%s\n' "$(printf '%s\n' "$plugin_output" | sed -n 's/^auto_maintain=//p' | head -n1)"
  printf 'managed_lug_version=%s\n' "${lug_version}"
  printf 'managed_wine_version=%s\n' "${wine_version}"
  printf 'managed_dxvk_version=%s\n' "${dxvk_version}"
  printf 'maintenance_result=%s\n' "$(printf '%s\n' "$plugin_output" | sed -n 's/^maintenance_result=//p' | head -n1)"
}

hardware_info() {
  local out reason gpu vulkan
  out="$(backend_game_status 2>/dev/null || true)"
  reason="$(printf '%s\n' "$out" | sed -n 's/^hardware_reason=//p')"
  gpu="$(printf '%s\n' "$out" | sed -n 's/^gpu=//p')"
  vulkan="$(printf '%s\n' "$out" | sed -n 's/^vulkan=//p')"
  if command -v zenity >/dev/null 2>&1; then
    zenity --warning --width=600 --title="Omarchy Citizen – Hardware" --text="<b>Star Citizen ist auf diesem System noch nicht spielbereit.</b>\n\nGPU:\n${gpu:-nicht erkannt}\n\nVulkan: ${vulkan:-unbekannt}\n\n${reason:-Hardware-Prüfung fehlgeschlagen.}" >/dev/null 2>&1 || true
  else
    printf '%s\n' "$reason"
  fi
}

probe_detached_start() {
  local label="$1"
  shift

  "$@" >>"$LOG_FILE" 2>&1 &
  local pid=$!

  sleep 0.45

  if ! kill -0 "$pid" 2>/dev/null; then
    local rc=0
    wait "$pid" || rc=$?
    if (( rc != 0 )); then
      log_line "$label failed rc=$rc"
      return "$rc"
    fi
  else
    disown "$pid" 2>/dev/null || true
  fi

  log_line "$label accepted"
  return 0
}

launch_terminal_action() {
  local action="$1"
  log_line "launch-terminal action=$action"

  # Prefer direct argv-safe terminal launching. This avoids the presentation
  # wrapper joining arguments into one shell command string.
  if command -v uwsm-app >/dev/null 2>&1 && command -v xdg-terminal-exec >/dev/null 2>&1; then
    if probe_detached_start "uwsm-xdg-terminal" \
      setsid uwsm-app -- xdg-terminal-exec \
        --app-id=org.omarchy.terminal \
        --title="Omarchy Citizen Setup" \
        -e bash "$SELF" "$action"; then
      printf 'terminal=opened\n'
      return 0
    fi
  fi

  if command -v xdg-terminal-exec >/dev/null 2>&1; then
    if probe_detached_start "xdg-terminal" \
      xdg-terminal-exec \
        --title="Omarchy Citizen Setup" \
        -e bash "$SELF" "$action"; then
      printf 'terminal=opened\n'
      return 0
    fi
  fi

  # Final compatibility fallback for older/current Omarchy installations.
  if command -v omarchy-launch-floating-terminal-with-presentation >/dev/null 2>&1; then
    if probe_detached_start "omarchy-floating-terminal" \
      omarchy-launch-floating-terminal-with-presentation bash "$SELF" "$action"; then
      printf 'terminal=opened\n'
      return 0
    fi
  fi

  echo "Das Setup-Terminal konnte nicht geöffnet werden." >&2
  notify_error "Das Setup-Terminal konnte nicht geöffnet werden.

Bitte klicke auf „Support-Paket erstellen“. Der fehlgeschlagene Startversuch ist dort protokolliert."
  return 1
}


backup_lug_target_configs() {
  local stamp="$1"
  local f
  mkdir -p "$CONFIG_DIR"
  for f in "$WINE_CONF" "$GAME_CONF"; do
    if [[ -f "$f" ]]; then
      mv -- "$f" "${f}.incomplete-${stamp}"
      log_line "backed up LUG config $(basename "$f") -> $(basename "${f}.incomplete-${stamp}")"
    fi
  done
}

stop_prefix_wineserver() {
  local prefix="$1"
  local wineserver=""

  # Kill only a wineserver associated with the runner inside this target prefix.
  # Do not kill unrelated Wine applications globally.
  wineserver="$(find "$prefix/runners" -type f -path '*/bin/wineserver' -perm -u+x -print -quit 2>/dev/null || true)"
  if [[ -n "$wineserver" ]]; then
    WINEPREFIX="$prefix" "$wineserver" -k >>"$LOG_FILE" 2>&1 || true
    sleep 0.5
  fi
}

recover_incomplete_prefix_terminal() {
  set -Ee
  exec > >(tee -a "$LOG_FILE") 2>&1

  local prefix stamp backup datap4k=""

  recovery_failed() {
    local rc=$?
    trap - ERR
    echo
    echo "=================================================="
    echo " REPARATUR KONNTE NICHT ABGESCHLOSSEN WERDEN"
    echo "=================================================="
    echo
    echo "Fehlercode: $rc"
    echo
    echo "Dein vorheriger Ordner wurde nicht gelöscht."
    echo "Im SC-Panel kannst du jetzt „Support-Paket erstellen“ wählen."
    echo
    log_line "recover-prefix-terminal failed rc=$rc"
    notify "Omarchy Citizen" "Setup-Reparatur fehlgeschlagen. Bitte erstelle ein Support-Paket."
    if [[ -t 0 ]]; then
      read -r -p "Drücke Enter, um dieses Fenster zu schließen … " _ || true
    else
      sleep 10
    fi
    exit "$rc"
  }
  trap recovery_failed ERR

  prefix="$(find_incomplete_prefix 2>/dev/null)" || {
    echo "Es wurde kein unvollständiger Wine-Prefix mehr gefunden."
    echo "Starte stattdessen die normale Einrichtung."
    log_line "recover-prefix-terminal no incomplete prefix found"
    trap - ERR
    return 0
  }

  datap4k="$prefix/drive_c/Program Files/Roberts Space Industries/StarCitizen/LIVE/Data.p4k"

  echo
  echo "=================================================="
  echo " Omarchy Citizen – Setup sicher reparieren"
  echo "=================================================="
  echo
  echo "Unvollständiger Wine-Prefix:"
  echo "  $prefix"
  echo

  # Never move real game data ourselves.
  if [[ -f "$datap4k" ]]; then
    echo "Vorhandene Star-Citizen-Spieldaten wurden erkannt."
    echo "Omarchy Citizen verschiebt diese Daten nicht selbst."
    echo "Die Reparatur wird an den LUG Helper übergeben."
    echo
    log_line "recover-prefix-terminal Data.p4k present; delegate to LUG"
    run_helper_visible --install
    trap - ERR
    return 0
  fi

  stamp="$(date '+%Y%m%d-%H%M%S')"
  backup="${prefix}-incomplete-${stamp}"

  echo "Der halbfertige Ordner wird NICHT gelöscht."
  echo "Er wird gesichert als:"
  echo "  $backup"
  echo
  echo "Danach wird der offizielle LUG-Installer sauber neu gestartet."
  echo

  log_line "recover-prefix-terminal prefix=$prefix backup=$backup"

  stop_prefix_wineserver "$prefix"

  mv -- "$prefix" "$backup"
  backup_lug_target_configs "$stamp"

  echo "✓ Backup erstellt."
  echo
  echo "Starte frische LUG-Einrichtung …"
  echo

  run_helper_visible --install

  echo
  echo "Prüfe den neu angelegten Wine-Prefix …"
  if read_prefix >/dev/null 2>&1; then
    echo "✓ Wine-Prefix ist vollständig initialisiert."
    log_line "recover-prefix-terminal succeeded"
    trap - ERR
    notify "Omarchy Citizen" "Wine-Prefix wurde erfolgreich neu erstellt."
    echo
    echo "Reparatur abgeschlossen. Du kannst dieses Fenster schließen."
    return 0
  fi

  echo
  echo "Der LUG-Installer wurde beendet, aber drive_c/system.reg/user.reg"
  echo "sind weiterhin nicht vollständig vorhanden."
  echo
  log_line "recover-prefix-terminal LUG returned but prefix still incomplete"
  return 1
}

recover_incomplete_prefix() {
  launch_terminal_action recover-prefix-terminal
}

guided_setup_interactive() {
  log_line "guided-setup begin"

  if ! find_helper >/dev/null 2>&1; then
    launch_terminal_action install-stack-terminal
    return 0
  fi

  if find_incomplete_prefix >/dev/null 2>&1; then
    log_line "guided setup found incomplete prefix; opening visible recovery terminal"
    launch_terminal_action recover-prefix-terminal
    return $?
  fi

  run_helper_sync --preflight-check || true

  if ! read_prefix >/dev/null 2>&1; then
    run_helper_sync --install || true
  elif ! prefix="$(read_prefix 2>/dev/null)" || [[ ! -f "$prefix/sc-launch.sh" ]]; then
    run_helper_sync --update-launch-script || true
  fi

  prefix="$(read_prefix 2>/dev/null || true)"
  if [[ -n "$prefix" && -f "$prefix/sc-launch.sh" ]]; then
    game_dir="$(read_game_dir 2>/dev/null || true)"
    if [[ -z "$game_dir" || ! -f "$game_dir/LIVE/Bin64/StarCitizen.exe" ]]; then
      log_line "guided-setup opening RSI Launcher for game installation"
      nohup bash "$prefix/sc-launch.sh" >>"$LOG_FILE" 2>&1 &
    fi
  fi

  notify "Omarchy Citizen" "Einrichtung abgeschlossen. Falls Star Citizen noch fehlt, ist der RSI Launcher für die Installation geöffnet."
  log_line "guided-setup end"
}

guided_setup() {
  launch_terminal_action install-stack-terminal
}

install_stack_terminal() {
  set -Ee
  exec > >(tee -a "$LOG_FILE") 2>&1

  setup_failed() {
    local rc=$?
    trap - ERR
    echo
    echo "=================================================="
    echo " SETUP KONNTE NICHT ABGESCHLOSSEN WERDEN"
    echo "=================================================="
    echo
    echo "Fehlercode: $rc"
    echo "Im SC-Panel kannst du mit einem Klick ein Support-Paket erstellen."
    log_line "owned-stack setup failed rc=$rc"
    notify "Omarchy Citizen" "Setup fehlgeschlagen. Bitte Support-Paket erstellen."
    if [[ -t 0 ]]; then read -r -p "Drücke Enter zum Schließen … " _ || true; fi
    exit "$rc"
  }
  trap setup_failed ERR

  echo
  echo "=================================================="
  echo " Omarchy Citizen – Spielbereit machen"
  echo "=================================================="
  echo
  echo "Omarchy Citizen verwaltet den kritischen Gaming-Stack jetzt selbst."
  echo "Der LUG Helper entscheidet nicht mehr, welche Wine-Version installiert wird."
  echo

  local hw
  hw="$(backend_game_status)"
  if [[ "$(printf '%s\n' "$hw" | sed -n 's/^health=//p')" == "hardware-blocked" ]]; then
    echo "Hardware-Prüfung nicht bestanden:"
    printf '%s\n' "$hw" | grep -E '^(hardware_reason|gpu|vulkan)='
    trap - ERR
    return 2
  fi

  echo "1/4 Autopilot aktivieren und Quellen synchronisieren …"
  autopilot_enable
  echo
  echo "2/4 Kompatiblen Wine-Runner prüfen …"
  wine_doctor
  echo
  echo "3/4 Wine-Prefix, Komponenten und RSI Launcher installieren/reparieren …"
  backend_game_install
  echo
  echo "4/4 Gaming-Stack abschließend synchronisieren …"
  autopilot_maintain || true

  trap - ERR
  echo
  echo "=================================================="
  echo " SOFTWARE-STACK BEREIT"
  echo "=================================================="
  echo
  echo "Der RSI Launcher kann jetzt gestartet werden."
  echo "Anmeldung und der eigentliche Spieldownload erfolgen im offiziellen RSI Launcher."
  notify "Omarchy Citizen" "Software-Stack ist bereit. RSI Launcher kann gestartet werden."
}

update_helper_terminal() {
  set -Ee
  exec > >(tee -a "$LOG_FILE") 2>&1
  echo "Synchronisiere LUG Helper, Wine Runner und DXVK über Autopilot …"
  autopilot_maintain
  echo "✓ Gaming-Stack ist aktuell."
}

system_update_terminal() {
  set -e
  log_line "omarchy update begin"
  omarchy update
  rm -f "$UPDATE_CACHE"
  log_line "omarchy update end rc=0"
}

launch_game() {
  log_line "launch via owned backend"
  if ! backend_game_launch >>"$LOG_FILE" 2>&1; then
    notify_error "Star Citizen konnte nicht gestartet werden. Nutze „Problem beheben“ oder erstelle ein Support-Paket."
    return 1
  fi
}

primary_action() {
  local st health backend
  backend="$(find_backend 2>/dev/null || true)"
  [[ -n "$backend" ]] && systemctl --user start omarchy-citizen-update.service >/dev/null 2>&1 || true
  st="$(status)"
  health="$(printf '%s\n' "$st" | sed -n 's/^health=//p' | head -n1)"
  case "$health" in
    ready|install-game)
      launch_game
      ;;
    hardware-blocked)
      hardware_info
      ;;
    *)
      launch_terminal_action install-stack-terminal
      ;;
  esac
}

repair_stack_terminal() {
  set -Ee
  exec > >(tee -a "$LOG_FILE") 2>&1
  echo "Omarchy Citizen prüft und repariert den gesamten Star-Citizen-Stack …"
  autopilot_maintain || true
  backend_game_repair
  echo "Reparatur abgeschlossen."
}

repair_assistant_interactive() {
  local st health
  st="$(status)"
  health="$(printf '%s\n' "$st" | sed -n 's/^health=//p' | head -n1)"
  if [[ "$health" == "hardware-blocked" ]]; then hardware_info; return; fi
  launch_terminal_action repair-stack-terminal
}

repair_assistant() { repair_assistant_interactive; }

sanitize_to() {
  local source="$1"
  local target="$2"

  if [[ ! -f "$source" ]]; then
    return 0
  fi

  if command -v python3 >/dev/null 2>&1 && [[ -f "$SANITIZER" ]]; then
    python3 "$SANITIZER" < "$source" > "$target"
  else
    sed \
      -e "s#${HOME//\#/\\#}#~#g" \
      -e 's/[A-Za-z0-9._%+-]\+@[A-Za-z0-9.-]\+\.[A-Za-z]\{2,\}/<email>/g' \
      "$source" > "$target"
  fi
}

capture_sanitized() {
  local target="$1"
  shift
  local tmp="$CACHE_DIR/capture-$$-$RANDOM.txt"
  {
    "$@"
  } >"$tmp" 2>&1 || true
  sanitize_to "$tmp" "$target"
  rm -f "$tmp"
}

support_build() {
  local stamp support_id work downloads archive prefix="" game_dir=""
  stamp="$(date '+%Y%m%d-%H%M%S')"
  support_id="OC-${stamp}-$(printf '%s-%s-%s' "$stamp" "$$" "$RANDOM" | sha256sum | cut -c1-6)"
  work="$CACHE_DIR/support-$support_id"

  if command -v xdg-user-dir >/dev/null 2>&1; then
    downloads="$(xdg-user-dir DOWNLOAD 2>/dev/null || true)"
  else
    downloads=""
  fi
  [[ -n "$downloads" && -d "$downloads" ]] || downloads="$HOME/Downloads"
  mkdir -p "$downloads" "$work"

  log_line "support build id=$support_id"

  cat > "$work/README_SUPPORT.txt" <<EOF
Omarchy Citizen Support-Paket
Support-ID: $support_id
Plugin-Version: $PLUGIN_VERSION
Erstellt: $(date '+%Y-%m-%d %H:%M:%S %z')

Dieses Paket wurde automatisch erstellt, um Support ohne Linux-Kenntnisse zu ermöglichen.

Datenschutz:
- Home-Pfad, Benutzername und Hostname werden beim Export maskiert.
- E-Mail-Adressen, IP-/MAC-Adressen und typische Token-/Session-Werte werden maskiert.
- Es werden keine Browserdaten, SSH-Schlüssel oder Passwortdateien gesammelt.
- Star-Citizen-Game.log/EAC-Vollprotokolle sind im Standardpaket NICHT enthalten.
- Die Maskierung ist eine Best-Effort-Funktion. Nutzer können das Archiv vor dem Senden prüfen.

Bitte bei Support-Anfragen die Support-ID mit angeben.
EOF

  {
    echo "support_id=$support_id"
    echo "plugin_id=$PLUGIN_ID"
    echo "plugin_version=$PLUGIN_VERSION"
    echo "created=$(date --iso-8601=seconds)"
    "$SELF" status
  } > "$work/citizen-status.txt"

  if backend="$(find_backend 2>/dev/null)"; then
    capture_sanitized "$work/updater-status.json" "$backend" status --json
  fi
  if [[ -f "$STATE_DIR/updater.log" ]]; then
    tail -n 1200 "$STATE_DIR/updater.log" > "$CACHE_DIR/updater-log-$$.txt"
    sanitize_to "$CACHE_DIR/updater-log-$$.txt" "$work/updater.log"
    rm -f "$CACHE_DIR/updater-log-$$.txt"
  fi

  capture_sanitized "$work/omarchy-debug.txt" omarchy debug --no-sudo --print

  if backend="$(find_backend 2>/dev/null)"; then
    capture_sanitized "$work/autopilot-status.txt" "$backend" status
    capture_sanitized "$work/game-status.txt" "$backend" game-status
    capture_sanitized "$work/wine-doctor.txt" "$backend" doctor
  fi

  {
    echo "=== Kernel / Desktop ==="
    uname -rmo 2>/dev/null || true
    printf 'XDG_SESSION_TYPE=%s\n' "${XDG_SESSION_TYPE:-unknown}"
    printf 'XDG_CURRENT_DESKTOP=%s\n' "${XDG_CURRENT_DESKTOP:-unknown}"
    printf 'WAYLAND_DISPLAY=%s\n' "${WAYLAND_DISPLAY:-unknown}"
    echo
    echo "=== Memory ==="
    free -h 2>/dev/null || true
    echo
    echo "=== Filesystems ==="
    df -hT / "$HOME" 2>/dev/null || true
    echo
    echo "=== Block devices ==="
    lsblk -o NAME,SIZE,FSTYPE,FSAVAIL,MOUNTPOINTS 2>/dev/null || true
    echo
    echo "=== GPU ==="
    lspci -nnk 2>/dev/null | grep -A4 -Ei 'VGA|3D|Display' || true
    echo
    echo "=== Vulkan ==="
    if command -v vulkaninfo >/dev/null 2>&1; then
      vulkaninfo --summary 2>/dev/null || true
    else
      echo "vulkaninfo not installed"
    fi
    echo
    echo "=== Star Citizen kernel limits ==="
    sysctl vm.max_map_count 2>/dev/null || true
    printf 'hard_open_files=%s\n' "$(ulimit -Hn 2>/dev/null || true)"
  } > "$CACHE_DIR/system-$$.txt"
  sanitize_to "$CACHE_DIR/system-$$.txt" "$work/system.txt"
  rm -f "$CACHE_DIR/system-$$.txt"

  {
    echo "=== Relevant packages ==="
    pacman -Q omarchy omarchy-dev lug-helper zenity polkit cabextract unzip 2>/dev/null || true
    echo
    echo "=== AUR helper ==="
    yay --version 2>/dev/null | head -n 4 || true
    echo
    echo "=== Commands ==="
    for cmd in omarchy lug-helper yay zenity wine winetricks gamescope gamemoderun; do
      if command -v "$cmd" >/dev/null 2>&1; then
        printf '%s=present\n' "$cmd"
      else
        printf '%s=missing\n' "$cmd"
      fi
    done
  } > "$work/packages.txt"

  if command -v omarchy >/dev/null 2>&1; then
    capture_sanitized "$work/plugin-validation.txt" omarchy plugin validate "$PLUGIN_DIR"
  fi

  if [[ -f "$LOG_FILE" ]]; then
    tail -n 1500 "$LOG_FILE" > "$CACHE_DIR/plugin-log-$$.txt"
    sanitize_to "$CACHE_DIR/plugin-log-$$.txt" "$work/omarchy-citizen.log"
    rm -f "$CACHE_DIR/plugin-log-$$.txt"
  fi

  if [[ -f /tmp/omarchy-update.log ]]; then
    tail -n 500 /tmp/omarchy-update.log > "$CACHE_DIR/update-log-$$.txt"
    sanitize_to "$CACHE_DIR/update-log-$$.txt" "$work/omarchy-update-tail.log"
    rm -f "$CACHE_DIR/update-log-$$.txt"
  fi

  # LUG Helper writes the detailed Wine-prefix installation output here.
  # This is the most useful file when winetricks/Wine prefix creation fails.
  latest_lug_install_log="$(find /tmp -maxdepth 1 -type f -name 'lughelper-install-*.log' -printf '%T@ %p\n' 2>/dev/null \
    | sort -nr | head -n1 | cut -d' ' -f2- || true)"
  if [[ -n "$latest_lug_install_log" && -f "$latest_lug_install_log" ]]; then
    tail -n 1200 "$latest_lug_install_log" > "$CACHE_DIR/lug-install-$$.txt"
    sanitize_to "$CACHE_DIR/lug-install-$$.txt" "$work/lug-helper-install-tail.log"
    rm -f "$CACHE_DIR/lug-install-$$.txt"
  fi

  configured="$(configured_prefix 2>/dev/null || true)"
  if [[ -n "$configured" ]]; then
    {
      printf 'configured_prefix=%s\n' "$configured"
      printf 'directory_exists=%s\n' "$([[ -d "$configured" ]] && echo yes || echo no)"
      printf 'drive_c=%s\n' "$([[ -d "$configured/drive_c" ]] && echo present || echo missing)"
      printf 'system_reg=%s\n' "$([[ -f "$configured/system.reg" ]] && echo present || echo missing)"
      printf 'user_reg=%s\n' "$([[ -f "$configured/user.reg" ]] && echo present || echo missing)"
      printf 'runner_dirs=%s\n' "$(find "$configured/runners" -mindepth 1 -maxdepth 1 -type d -printf '%f ' 2>/dev/null || true)"
    } > "$CACHE_DIR/prefix-health-$$.txt"
    sanitize_to "$CACHE_DIR/prefix-health-$$.txt" "$work/wine-prefix-health.txt"
    rm -f "$CACHE_DIR/prefix-health-$$.txt"
  fi

  prefix="$(read_prefix 2>/dev/null || true)"
  game_dir="$(read_game_dir 2>/dev/null || true)"

  {
    printf 'wine_prefix=%s\n' "${prefix:-not-configured}"
    printf 'game_dir=%s\n' "${game_dir:-not-configured}"
    printf 'launch_script=%s\n' "$([[ -n "$prefix" && -f "$prefix/sc-launch.sh" ]] && echo present || echo missing)"
    printf 'game_binary=%s\n' "$([[ -n "$game_dir" && -f "$game_dir/LIVE/Bin64/StarCitizen.exe" ]] && echo present || echo missing)"
  } > "$CACHE_DIR/paths-$$.txt"
  sanitize_to "$CACHE_DIR/paths-$$.txt" "$work/star-citizen-path-status.txt"
  rm -f "$CACHE_DIR/paths-$$.txt"

  if [[ -n "$prefix" && -f "$prefix/sc-launch.log" ]]; then
    tail -n 600 "$prefix/sc-launch.log" > "$CACHE_DIR/sc-launch-$$.txt"
    sanitize_to "$CACHE_DIR/sc-launch-$$.txt" "$work/sc-launch-tail.log"
    rm -f "$CACHE_DIR/sc-launch-$$.txt"
  fi

  if [[ -n "$prefix" && -f "$prefix/sc-launch.sh" ]]; then
    head -n 350 "$prefix/sc-launch.sh" > "$CACHE_DIR/sc-script-$$.txt"
    sanitize_to "$CACHE_DIR/sc-script-$$.txt" "$work/sc-launch-script-sanitized.txt"
    rm -f "$CACHE_DIR/sc-script-$$.txt"
  fi

  archive="$downloads/Omarchy-Citizen-Support-$support_id.tar.gz"
  tar -C "$work" -czf "$archive" .
  rm -rf "$work"

  log_line "support archive=$archive"

  if command -v wl-copy >/dev/null 2>&1; then
    printf '%s' "$archive" | wl-copy
  fi

  if command -v zenity >/dev/null 2>&1; then
    zenity --info --width=580 \
      --title="Support-Paket erstellt" \
      --text="Support-ID:
<b>$support_id</b>

Das bereinigte Support-Paket wurde in deinem Downloads-Ordner erstellt:

$(basename "$archive")

Der Dateipfad wurde – falls die Zwischenablage verfügbar ist – kopiert.

Schicke dieses Archiv zusammen mit der Support-ID an den Plugin-Support." \
      >/dev/null 2>&1 || true
  else
    notify "Omarchy Citizen" "Support-Paket erstellt: $(basename "$archive")"
  fi

  if command -v xdg-open >/dev/null 2>&1; then
    xdg-open "$downloads" >/dev/null 2>&1 &
  fi

  printf '%s\n' "$archive"
}

support_start() {
  support_build
}

open_debug_log() {
  if [[ ! -f "$LOG_FILE" ]]; then
    notify_error "Noch kein Debug-Log vorhanden."
    return 1
  fi
  xdg-open "$LOG_FILE" >/dev/null 2>&1 &
}

open_log() {
  local prefix log
  prefix="$(read_prefix 2>/dev/null)" || {
    notify_error "Noch kein Star-Citizen-Wine-Prefix gefunden."
    return 1
  }

  log="$prefix/sc-launch.log"
  if [[ ! -f "$log" ]]; then
    notify_error "Noch kein Start-Log gefunden.

Starte den RSI Launcher mindestens einmal."
    return 1
  fi

  xdg-open "$log" >/dev/null 2>&1 &
}

open_wiki() {
  xdg-open "https://wiki.starcitizen-lug.org" >/dev/null 2>&1 &
}

open_ngl_page() {
  xdg-open "https://www.nglproject.com/de#downloads" >/dev/null 2>&1 &
}

ngl_info() {
  local msg
  msg="NGL ist ein optionaler Community-Mod für den Windows-RSI-Launcher.

Omarchy Citizen behandelt NGL als EXPERIMENTELL und installiert es nie ohne deine Auswahl und Bestätigung.

Der Mod läuft im selben Wine-Prefix wie dein RSI Launcher."

  if command -v zenity >/dev/null 2>&1; then
    zenity --info --width=520 --title="Omarchy Citizen – NGL" --text="$msg" >/dev/null 2>&1 &
  else
    notify "Omarchy Citizen – NGL" "$msg"
  fi
}

ngl_install_interactive() {
  local prefix script selected workdir exe

  if ! command -v zenity >/dev/null 2>&1; then
    notify_error "Die NGL-Installation benötigt die grafische Dateiauswahl. Bitte zuerst das normale Setup ausführen."
    return 1
  fi

  prefix="$(read_prefix 2>/dev/null)" || {
    notify_error "Star Citizen muss zuerst eingerichtet werden."
    return 1
  }

  script="$prefix/sc-launch.sh"
  [[ -f "$script" ]] || {
    notify_error "Das Star-Citizen-Start-Script fehlt. Nutze zuerst „Problem beheben“."
    return 1
  }

  selected="$(zenity \
    --file-selection \
    --title="NGL Installer auswählen" \
    --filename="$HOME/Downloads/" \
    --file-filter="NGL Installer | *.zip *.ZIP *.exe *.EXE" \
    --file-filter="Alle Dateien | *" 2>/dev/null)" || return 0

  [[ -f "$selected" ]] || return 1

  workdir="$CACHE_DIR/ngl-installer"
  rm -rf -- "$workdir"
  mkdir -p "$workdir"

  case "${selected,,}" in
    *.zip)
      unzip -q "$selected" -d "$workdir" || {
        notify_error "Der NGL-Installer konnte nicht entpackt werden."
        return 1
      }
      exe="$(find "$workdir" -type f \( -iname '*ngl*.exe' -o -iname '*installer*.exe' -o -iname '*setup*.exe' -o -iname '*.exe' \) \
        -printf '%p\n' | head -n 1)"
      ;;
    *.exe)
      exe="$selected"
      ;;
    *)
      notify_error "Bitte eine NGL-ZIP- oder EXE-Datei auswählen."
      return 1
      ;;
  esac

  [[ -n "${exe:-}" && -f "$exe" ]] || {
    notify_error "Kein Windows-Installer in der ausgewählten Datei gefunden."
    return 1
  }

  if ! zenity --question --width=560 \
    --title="NGL experimentell installieren?" \
    --ok-label="Installer starten" \
    --cancel-label="Abbrechen" \
    --text="NGL ist Community-Code und läuft im selben Wine-Prefix wie dein RSI Launcher.

Bitte nutze ausschließlich Downloads von nglproject.com.

Fortfahren?" 2>/dev/null; then
    return 0
  fi

  log_line "NGL installer confirmed by user"

  {
    printf 'wine '
    printf '%q' "$exe"
    printf '\nexit\n'
  } | bash "$script" shell >>"$LOG_FILE" 2>&1
}

ngl_install() {
  ngl_install_interactive
}

case "$ACTION" in
  status)                   status ;;
  hardware-info)            hardware_info ;;
  autopilot-enable)         autopilot_enable ;;
  autopilot-maintain)       autopilot_maintain ;;
  wine-doctor)              wine_doctor ;;
  primary)                  primary_action ;;
  setup)                    guided_setup ;;
  recover-prefix)           recover_incomplete_prefix ;;
  recover-prefix-terminal)   recover_incomplete_prefix_terminal ;;
  guided-setup-interactive) guided_setup_interactive ;;
  repair)                   repair_assistant ;;
  repair-interactive)       repair_assistant_interactive ;;
  repair-stack-terminal)     repair_stack_terminal ;;
  support)                  support_start ;;
  support-build)            support_build ;;
  debug-log)                open_debug_log ;;
  plugin-update-check)       plugin_update_check ;;
  plugin-update-now)         plugin_update_now ;;
  plugin-auto-enable)        plugin_auto_enable ;;
  plugin-auto-disable)       plugin_auto_disable ;;
  updater-log)               open_updater_log ;;
  check-update)             check_update ;;
  install-stack)            launch_terminal_action install-stack-terminal ;;
  install-stack-terminal)   install_stack_terminal ;;
  update-helper)            launch_terminal_action update-helper-terminal ;;
  update-helper-terminal)   update_helper_terminal ;;
  system-update)            launch_terminal_action system-update-terminal ;;
  system-update-terminal)   system_update_terminal ;;
  launch)                   launch_game ;;
  helper)                   run_helper_gui ;;
  install)                  run_helper_gui --install ;;
  preflight)                run_helper_gui --preflight-check ;;
  runners)                  run_helper_gui --manage-runners ;;
  dxvk)                     run_helper_gui --manage-dxvk ;;
  repair-launch)            run_helper_gui --update-launch-script ;;
  repair-rsi)               run_helper_gui --update-rsi-launcher ;;
  dirs)                     run_helper_gui --show-directories ;;
  log)                      open_log ;;
  wiki)                     open_wiki ;;
  ngl-page)                 open_ngl_page ;;
  ngl-info)                 ngl_info ;;
  ngl-install)              ngl_install ;;
  ngl-install-interactive)  ngl_install_interactive ;;
  *)
    notify_error "Unbekannte Omarchy-Citizen-Aktion: $ACTION"
    exit 2
    ;;
esac
