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

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

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"

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 backend
  backend="$(find_backend 2>/dev/null)" || return 1
  "$backend" status
}

plugin_update_check() {
  local backend output state
  backend="$(find_backend 2>/dev/null)" || {
    notify_error "Das Omarchy-Citizen-Update-Backend wurde nicht gefunden. Installiere das Plugin erneut."
    return 1
  }
  output="$($backend check 2>&1)" || true
  printf '%s\n' "$output" >> "$LOG_FILE"
  state="$(printf '%s\n' "$output" | sed -n 's/^update=//p' | head -n1)"
  case "$state" in
    available) notify "Omarchy Citizen" "Ein Plugin-Update ist verfügbar." ;;
    current) notify "Omarchy Citizen" "Omarchy Citizen ist aktuell." ;;
    unavailable) notify "Omarchy Citizen" "Diese Installation ist noch nicht Git-verwaltet. Automatische Plugin-Updates werden nach der Git-Installation verfügbar." ;;
    blocked-dirty) notify_error "Plugin-Update blockiert: Im Plugin-Verzeichnis gibt es lokale Änderungen." ;;
    blocked-remote-changed) notify_error "Plugin-Update aus Sicherheitsgründen blockiert: Das Git-Remote hat sich geändert." ;;
    *) notify_error "Plugin-Update konnte nicht eindeutig geprüft werden. Das Support-Paket enthält Details." ;;
  esac
}

plugin_update_now() {
  local backend
  backend="$(find_backend 2>/dev/null)" || {
    notify_error "Das Update-Backend wurde nicht gefunden."
    return 1
  }
  if "$backend" update >>"$LOG_FILE" 2>&1; then
    notify "Omarchy Citizen" "Plugin-Update abgeschlossen."
  else
    notify_error "Plugin-Update fehlgeschlagen oder nicht verfügbar. Erstelle bei Bedarf ein Support-Paket."
  fi
}

plugin_auto_enable() {
  local backend
  backend="$(find_backend 2>/dev/null)" || { notify_error "Update-Backend fehlt."; return 1; }
  if "$backend" auto enable >>"$LOG_FILE" 2>&1; then
    notify "Omarchy Citizen" "Automatische Plugin-Updates sind aktiviert."
  else
    notify_error "Auto-Updates konnten nicht aktiviert werden. Bei ZIP-Installationen ist zuerst eine Git-verwaltete Plugin-Installation nötig."
  fi
}

plugin_auto_disable() {
  local backend
  backend="$(find_backend 2>/dev/null)" || { notify_error "Update-Backend fehlt."; return 1; }
  "$backend" auto disable >>"$LOG_FILE" 2>&1 || true
  notify "Omarchy Citizen" "Automatische Plugin-Updates sind deaktiviert."
}

open_updater_log() {
  local log="$STATE_DIR/updater.log"
  if [[ ! -f "$log" ]]; then
    notify_error "Noch kein Updater-Log vorhanden."
    return 1
  fi
  xdg-open "$log" >/dev/null 2>&1 &
}

notify() {
  local title="$1"
  local message="$2"
  if command -v omarchy-notification-send >/dev/null 2>&1; then
    omarchy-notification-send "$title" "$message" >/dev/null 2>&1 || true
  elif command -v notify-send >/dev/null 2>&1; then
    notify-send "$title" "$message" >/dev/null 2>&1 || true
  fi
}

notify_error() {
  local message="$1"
  log_line "error=$message"
  if command -v zenity >/dev/null 2>&1; then
    zenity --error --width=500 --title="Omarchy Citizen" --text="$message" >/dev/null 2>&1 &
  else
    notify "Omarchy Citizen" "$message"
    printf 'Omarchy Citizen: %s\n' "$message" >&2
  fi
}

find_helper() {
  local candidate

  if command -v lug-helper >/dev/null 2>&1; then
    command -v lug-helper
    return 0
  fi

  if command -v lug-helper.sh >/dev/null 2>&1; then
    command -v lug-helper.sh
    return 0
  fi

  for candidate in \
    "$HOME/.local/bin/lug-helper" \
    "$HOME/.local/bin/lug-helper.sh" \
    "$DATA_DIR/lug-helper/lug-helper.sh" \
    "$HOME/lug-helper/lug-helper.sh"
  do
    if [[ -f "$candidate" ]]; then
      printf '%s\n' "$candidate"
      return 0
    fi
  done

  shopt -s nullglob
  for candidate in \
    "$HOME/Applications"/*LUG*Helper*.AppImage \
    "$HOME/Applications"/lug-helper*.AppImage \
    "$HOME/Downloads"/*LUG*Helper*.AppImage \
    "$HOME/Downloads"/lug-helper*.AppImage
  do
    if [[ -x "$candidate" ]]; then
      printf '%s\n' "$candidate"
      shopt -u nullglob
      return 0
    fi
  done
  shopt -u nullglob

  return 1
}

run_helper_sync() {
  local helper
  helper="$(find_helper)" || {
    notify_error "Der Star Citizen LUG Helper wurde nicht gefunden."
    return 1
  }

  log_line "lug-helper sync args=$*"
  if [[ "$helper" == *.sh ]]; then
    bash "$helper" "$@" >>"$LOG_FILE" 2>&1
  else
    "$helper" "$@" >>"$LOG_FILE" 2>&1
  fi
}

run_helper_visible() {
  local helper
  helper="$(find_helper)" || {
    echo "Der Star Citizen LUG Helper wurde nicht gefunden." >&2
    return 1
  }

  log_line "lug-helper visible args=$*"
  if [[ "$helper" == *.sh ]]; then
    bash "$helper" "$@"
  else
    "$helper" "$@"
  fi
}

run_helper_gui() {
  local helper
  helper="$(find_helper)" || {
    notify_error "Der Star Citizen LUG Helper wurde nicht gefunden.

Wähle im SC-Panel „Einrichten“ – Omarchy Citizen installiert die benötigten Komponenten."
    return 1
  }

  log_line "lug-helper gui args=$*"
  if [[ "$helper" == *.sh ]]; then
    nohup bash "$helper" "$@" >>"$LOG_FILE" 2>&1 &
  else
    nohup "$helper" "$@" >>"$LOG_FILE" 2>&1 &
  fi
}

configured_prefix() {
  [[ -f "$WINE_CONF" ]] || return 1
  local prefix
  IFS= read -r prefix < "$WINE_CONF"
  [[ -n "$prefix" ]] || return 1
  printf '%s\n' "$prefix"
}

prefix_is_initialized() {
  local prefix="$1"
  [[ -d "$prefix/drive_c" ]] &&
  [[ -f "$prefix/system.reg" ]] &&
  [[ -f "$prefix/user.reg" ]]
}

read_prefix() {
  local prefix
  prefix="$(configured_prefix 2>/dev/null)" || return 1
  [[ -d "$prefix" ]] || return 1
  prefix_is_initialized "$prefix" || return 1
  printf '%s\n' "$prefix"
}

find_incomplete_prefix() {
  local prefix=""

  prefix="$(configured_prefix 2>/dev/null || true)"
  if [[ -n "$prefix" && -d "$prefix" ]] && ! prefix_is_initialized "$prefix"; then
    printf '%s\n' "$prefix"
    return 0
  fi

  prefix="$HOME/Games/star-citizen"
  if [[ -d "$prefix" ]] && ! prefix_is_initialized "$prefix"; then
    # Only treat the default path as our incomplete prefix when it contains
    # LUG/installation artifacts rather than an arbitrary empty user folder.
    if [[ -d "$prefix/runners" || -f "$prefix/sc-launch.sh" || -f "$prefix/.lughelper" ]]; then
      printf '%s\n' "$prefix"
      return 0
    fi
  fi

  return 1
}

read_game_dir() {
  [[ -f "$GAME_CONF" ]] || return 1
  local game_dir
  IFS= read -r game_dir < "$GAME_CONF"
  [[ -n "$game_dir" ]] || return 1
  printf '%s\n' "$game_dir"
}

package_installed() {
  pacman -Qq "$1" >/dev/null 2>&1
}

installed_lug_version() {
  pacman -Q lug-helper 2>/dev/null | awk '{print $2}'
}

read_update_cache() {
  local key="$1"
  [[ -f "$UPDATE_CACHE" ]] || return 1
  sed -n "s/^${key}=//p" "$UPDATE_CACHE" | head -n 1
}

write_update_cache() {
  local state="$1"
  local version="${2:-}"
  mkdir -p "$CACHE_DIR"
  {
    printf 'state=%s\n' "$state"
    printf 'version=%s\n' "$version"
    printf 'checked_at=%s\n' "$(date +%s)"
  } > "$UPDATE_CACHE"
}

check_update() {
  local installed output rc line target=""

  if ! package_installed lug-helper; then
    write_update_cache "not-installed" ""
    printf 'not-installed\n'
    return 0
  fi

  installed="$(installed_lug_version)"

  if ! command -v yay >/dev/null 2>&1; then
    write_update_cache "unknown" ""
    printf 'unknown\n'
    return 1
  fi

  set +e
  output="$(timeout 25s yay -Qua 2>/dev/null)"
  rc=$?
  set -e

  if (( rc != 0 )); then
    write_update_cache "unknown" ""
    printf 'unknown\n'
    return 1
  fi

  line="$(printf '%s\n' "$output" | awk '$1=="lug-helper"{print; exit}')"
  if [[ -n "$line" ]]; then
    target="$(printf '%s\n' "$line" | awk '{print $NF}')"
    write_update_cache "available" "$target"
    printf 'available=%s\n' "$target"
  else
    write_update_cache "current" "$installed"
    printf 'current=%s\n' "$installed"
  fi
}

status() {
  local helper="" version="" prefix="" game_dir="" dep missing_deps=""
  local helper_state="missing" helper_managed="missing" deps_state="ready"
  local prefix_state="missing" prefix_detail="" launcher_state="missing" game_state="missing"
  local update_state="unknown" update_version="" health="setup"

  for dep in "${GUI_PACKAGES[@]}"; do
    if ! package_installed "$dep"; then
      deps_state="missing"
      if [[ -n "$missing_deps" ]]; then missing_deps+=","; fi
      missing_deps+="$dep"
    fi
  done

  if package_installed lug-helper; then
    helper_state="ready"
    helper_managed="aur"
    version="$(installed_lug_version)"
  elif helper="$(find_helper 2>/dev/null)"; then
    helper_state="ready"
    helper_managed="external"
    if [[ "$helper" == *.sh ]]; then
      version="$(bash "$helper" --version 2>/dev/null | head -n 1 || true)"
    else
      version="$("$helper" --version 2>/dev/null | head -n 1 || true)"
    fi
    version="${version//$'\n'/ }"
    version="${version//$'\r'/ }"
  fi

  update_state="$(read_update_cache state 2>/dev/null || printf 'unknown')"
  update_version="$(read_update_cache version 2>/dev/null || true)"

  if prefix="$(read_prefix 2>/dev/null)"; then
    prefix_state="ready"
    prefix_detail="initialisiert"
    if [[ -f "$prefix/sc-launch.sh" ]]; then
      launcher_state="ready"
    fi
  elif prefix="$(find_incomplete_prefix 2>/dev/null)"; then
    prefix_state="partial"
    prefix_detail="unvollständig"
  fi

  if game_dir="$(read_game_dir 2>/dev/null)"; then
    if [[ -f "$game_dir/LIVE/Bin64/StarCitizen.exe" ]]; then
      game_state="ready"
    elif [[ -d "$game_dir" ]]; then
      game_state="partial"
    fi
  fi

  if [[ "$deps_state" != "ready" || "$helper_state" != "ready" ]]; then
    health="setup"
  elif [[ "$prefix_state" == "partial" ]]; then
    health="recover-prefix"
  elif [[ "$prefix_state" != "ready" ]]; then
    health="install"
  elif [[ "$launcher_state" != "ready" ]]; then
    health="repair"
  elif [[ "$game_state" != "ready" ]]; then
    health="install-game"
  else
    health="ready"
  fi

  printf 'plugin_version=%s\n' "$PLUGIN_VERSION"
  printf 'health=%s\n' "$health"
  printf 'deps=%s\n' "$deps_state"
  printf 'deps_missing=%s\n' "$missing_deps"
  printf 'helper=%s\n' "$helper_state"
  printf 'helper_managed=%s\n' "$helper_managed"
  printf 'helper_version=%s\n' "$version"
  printf 'update=%s\n' "$update_state"
  printf 'update_version=%s\n' "$update_version"
  printf 'prefix=%s\n' "$prefix_state"
  printf 'prefix_detail=%s\n' "$prefix_detail"
  printf 'launcher=%s\n' "$launcher_state"
  printf 'game=%s\n' "$game_state"

  local backend_output="" backend_state="missing"
  if backend_output="$(backend_status 2>/dev/null)"; then
    backend_state="ready"
  fi
  printf 'backend=%s\n' "$backend_state"
  printf 'backend_version=%s\n' "$(printf '%s\n' "$backend_output" | sed -n 's/^backend_version=//p' | head -n1)"
  printf 'plugin_managed=%s\n' "$(printf '%s\n' "$backend_output" | sed -n 's/^managed=//p' | head -n1)"
  printf 'plugin_auto=%s\n' "$(printf '%s\n' "$backend_output" | sed -n 's/^auto_apply=//p' | head -n1)"
  printf 'plugin_update=%s\n' "$(printf '%s\n' "$backend_output" | sed -n 's/^update=//p' | head -n1)"
  printf 'plugin_local_commit=%s\n' "$(printf '%s\n' "$backend_output" | sed -n 's/^local_commit=//p' | head -n1)"
  printf 'plugin_remote_commit=%s\n' "$(printf '%s\n' "$backend_output" | sed -n 's/^remote_commit=//p' | head -n1)"
}

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() {
  if ! package_installed zenity || ! find_helper >/dev/null 2>&1; then
    launch_terminal_action install-stack-terminal
    return
  fi
  guided_setup_interactive
}

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 "Keine Sorge: Im SC-Panel kannst du anschließend"
    echo "„Support-Paket erstellen“ wählen."
    echo
    log_line "install-stack failed rc=$rc"
    notify "Omarchy Citizen" "Setup fehlgeschlagen. Bitte erstelle im SC-Panel ein Support-Paket."
    if [[ -t 0 ]]; then
      read -r -p "Drücke Enter, um dieses Fenster zu schließen … " _ || true
    else
      sleep 8
    fi
    exit "$rc"
  }
  trap setup_failed ERR

  echo
  echo "=================================================="
  echo " Omarchy Citizen – Plug & Play Setup"
  echo "=================================================="
  echo
  echo "Omarchy Citizen richtet die Linux-Gaming-Basis ein."
  echo "Du musst keine Paketnamen oder Linux-Befehle kennen."
  echo
  echo "Installiert/überprüft werden:"
  echo "  - zenity / polkit"
  echo "  - cabextract / unzip"
  echo "  - Star Citizen LUG Helper aus dem AUR"
  echo

  omarchy pkg add zenity polkit cabextract unzip

  if package_installed lug-helper; then
    echo "LUG Helper ist bereits installiert."
  else
    echo "Installiere LUG Helper..."
    omarchy pkg aur add lug-helper
  fi

  rm -f "$UPDATE_CACHE"

  echo
  echo "Systempakete sind bereit."
  echo "Als Nächstes startet der grafische Star-Citizen-Assistent."
  echo

  run_helper_sync --preflight-check || true

  if find_incomplete_prefix >/dev/null 2>&1; then
    echo
    echo "Eine frühere, unvollständige Wine-Prefix-Erstellung wurde erkannt."
    echo "Öffne die sichere Reparatur in einem eigenen Fenster."
    echo
    trap - ERR
    launch_terminal_action recover-prefix-terminal
    return 0
  elif ! read_prefix >/dev/null 2>&1; then
    run_helper_sync --install || true
  fi

  echo
  echo "Plug-&-Play-Setup beendet."
  echo "Du kannst dieses Fenster schließen und ✦SC öffnen."
  trap - ERR
  notify "Omarchy Citizen" "Grundsetup abgeschlossen. Öffne ✦SC und starte Star Citizen."
  log_line "install-stack complete"
}

update_helper_terminal() {
  set -e
  exec > >(tee -a "$LOG_FILE") 2>&1

  if ! package_installed lug-helper; then
    echo "LUG Helper ist noch nicht als AUR-Paket installiert."
    echo "Starte bitte zuerst das normale Omarchy-Citizen-Setup."
    exit 1
  fi

  echo "Aktualisiere den LUG Helper..."
  omarchy pkg aur add lug-helper
  rm -f "$UPDATE_CACHE"
  echo "LUG Helper ist aktuell."
  installed_lug_version
  log_line "lug-helper update complete"
}

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() {
  local prefix script
  prefix="$(read_prefix 2>/dev/null)" || {
    guided_setup
    return
  }

  script="$prefix/sc-launch.sh"
  if [[ ! -f "$script" ]]; then
    log_line "launch script missing; opening repair"
    run_helper_gui --update-launch-script
    return
  fi

  log_line "launch game via sc-launch.sh"
  nohup bash "$script" >>"$LOG_FILE" 2>&1 &
}

primary_action() {
  local st health
  st="$("$SELF" status)"
  health="$(printf '%s\n' "$st" | sed -n 's/^health=//p' | head -n1)"

  case "$health" in
    ready)
      launch_game
      ;;
    setup)
      launch_terminal_action install-stack-terminal
      ;;
    recover-prefix)
      recover_incomplete_prefix
      ;;
    install)
      guided_setup
      ;;
    install-game)
      launch_game
      ;;
    repair)
      run_helper_gui --update-launch-script
      ;;
    *)
      guided_setup
      ;;
  esac
}

repair_assistant_interactive() {
  local st health choice prefix

  st="$("$SELF" status)"
  health="$(printf '%s\n' "$st" | sed -n 's/^health=//p' | head -n1)"
  log_line "repair health=$health"

  case "$health" in
    setup)
      launch_terminal_action install-stack-terminal
      return
      ;;
    recover-prefix)
      launch_terminal_action recover-prefix-terminal
      return
      ;;
    install)
      guided_setup_interactive
      return
      ;;
    repair)
      run_helper_sync --update-launch-script || true
      notify "Omarchy Citizen" "Start-Script wurde geprüft/repariert. Versuche den Start erneut."
      return
      ;;
  esac

  if ! command -v zenity >/dev/null 2>&1; then
    run_helper_gui --preflight-check
    return
  fi

  choice="$(zenity --list \
    --width=610 --height=420 \
    --title="Omarchy Citizen – Problem beheben" \
    --text="Was funktioniert nicht? Du brauchst keine Linux-Diagnose zu kennen." \
    --column="Problem" \
    "Automatisch prüfen (empfohlen)" \
    "RSI Launcher startet nicht / ist kaputt" \
    "Star Citizen startet nicht" \
    "Grafik / Performance / Abstürze" \
    "NGL macht Probleme" \
    "Problem ist unklar – Support-Paket erstellen" \
    2>/dev/null)" || return 0

  log_line "repair choice=$choice"

  case "$choice" in
    "Automatisch prüfen (empfohlen)")
      run_helper_sync --preflight-check || true
      run_helper_sync --update-launch-script || true
      notify "Omarchy Citizen" "Automatische Basisreparatur abgeschlossen. Bitte erneut starten."
      ;;
    "RSI Launcher startet nicht / ist kaputt")
      run_helper_sync --update-rsi-launcher || true
      run_helper_sync --update-launch-script || true
      notify "Omarchy Citizen" "RSI Launcher und Start-Script wurden repariert."
      ;;
    "Star Citizen startet nicht")
      run_helper_sync --preflight-check || true
      run_helper_sync --update-launch-script || true
      notify "Omarchy Citizen" "Startumgebung wurde geprüft. Falls es weiter nicht startet, erstelle bitte das Support-Paket."
      ;;
    "Grafik / Performance / Abstürze")
      run_helper_sync --preflight-check || true
      run_helper_gui --manage-runners
      ;;
    "NGL macht Probleme")
      if zenity --question --width=540 \
        --title="NGL Problem" \
        --ok-label="Vanilla RSI Launcher reparieren" \
        --cancel-label="Abbrechen" \
        --text="Omarchy Citizen kann den offiziellen RSI Launcher über den LUG Helper neu installieren. NGL kann danach optional erneut installiert werden." \
        2>/dev/null; then
        run_helper_sync --update-rsi-launcher || true
        run_helper_sync --update-launch-script || true
      fi
      ;;
    "Problem ist unklar – Support-Paket erstellen")
      "$SELF" support-build
      ;;
  esac
}

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

  {
    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 ;;
  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 ;;
  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
