#!/bin/sh
# =============================================================================
# epc670_setup_desktop
# Applies per-user configuration for epc670: group membership, waybar/labwc
# configs, autostart and desktop entries, and bashrc venv block.
# Operates on the user passed as $1, or falls back to SUDO_USER /
# users.conf / "epc" in that order.
#
# Must be run as root (e.g. via sudo).
#
# Usage:
#   sudo epc670_setup_desktop [username]
# =============================================================================
set -e

is_live_system() {
  [ -d /run/systemd/system ]
}

# -----------------------------------------------------------------------------
# Require root
# -----------------------------------------------------------------------------
if [ "$(id -u)" -ne 0 ]; then
  echo "Error: this script must be run as root. Try: sudo $0 $*" >&2
  exit 1
fi

VENV_GROUP="epc670"
DOT_CONFIG_WAYBAR="/usr/share/epc670-tofhat-utils/.config/waybar/"
DOT_CONFIG_LABWC="/usr/share/epc670-tofhat-utils/.config/labwc/autostart"
BACKUP_BASE="/usr/share/epc670-tofhat-utils/backups"
USERS_CONF="/usr/share/epc670/users.conf"
DESKTOP_STAMP="/var/lib/epc670/desktop-setup-done"
AUTOSTART_DESKTOPS="TOFcam-670.desktop"
DESKTOP_SYMLINKS="epc670-docs.desktop epc670-update.desktop TOFcam-670.desktop"
WAYBAR_FILES="config.jsonc style.css"
BASHRC_APPEND="/usr/lib/epc670-tofhat-utils/epc670-bashrc-append"

log() {
  echo "epc670_setup_desktop: $*"
  logger -t epc670_setup_desktop "$*" || true
}

# -----------------------------------------------------------------------------
# Check and install missing dependencies (waybar, labwc)
# -----------------------------------------------------------------------------
MISSING_DEPS=""
command -v waybar >/dev/null 2>&1 || MISSING_DEPS="$MISSING_DEPS waybar"
command -v labwc  >/dev/null 2>&1 || MISSING_DEPS="$MISSING_DEPS labwc"

install_missing_deps() {
  if [ -n "$MISSING_DEPS" ]; then
    log "The following required packages are not installed:$MISSING_DEPS"

    # When invoked from a maintainer script, dpkg holds the packaging lock.
    # Calling apt-get/dnf/pacman here would block forever waiting on that lock
    # (the same class of deadlock as running `apt purge` from prerm). Skip the
    # auto-install in that case and rely on the package's own dependencies, or
    # a later manual run, to provide them.
    if [ -n "${DPKG_RUNNING_VERSION:-}" ]; then
      log "Running under dpkg; skipping automatic dependency installation."
      log "Ensure these are installed via package dependencies:$MISSING_DEPS"
      return
    fi

    log "Attempting to install missing packages..."
    if command -v apt-get >/dev/null 2>&1; then
      apt-get update -qq
      # shellcheck disable=SC2086
      apt-get install -y $MISSING_DEPS
    elif command -v dnf >/dev/null 2>&1; then
      # shellcheck disable=SC2086
      dnf install -y $MISSING_DEPS
    elif command -v pacman >/dev/null 2>&1; then
      # shellcheck disable=SC2086
      pacman -Sy --noconfirm $MISSING_DEPS
    else
      echo "Error: no supported package manager found (apt-get, dnf, pacman)." >&2
      echo "       Please install the following packages manually:$MISSING_DEPS" >&2
      exit 1
    fi

    # Verify installation succeeded
    FAILED_DEPS=""
    for dep in $MISSING_DEPS; do
      command -v "$dep" >/dev/null 2>&1 || FAILED_DEPS="$FAILED_DEPS $dep"
    done

    if [ -n "$FAILED_DEPS" ]; then
      echo ""
      echo "╔══════════════════════════════════════════════════════════════╗"
      echo "║  ✖ Dependency installation failed                            ║"
      echo "║                                                              ║"
      echo "║  The following packages could not be installed:              ║"
      for dep in $FAILED_DEPS; do
        printf "║    %-60s║\n" "• $dep"
      done
      echo "║                                                              ║"
      echo "║  Please install them manually:                               ║"
      echo "║                                                              ║"
      printf "║    %-60s║\n" "sudo apt-get install$FAILED_DEPS"
      echo "║                                                              ║"
      echo "║  Then re-run desktop setup:                                  ║"
      echo "║                                                              ║"
      echo "║    sudo epc670-setup-desktop                                 ║"
      echo "║                                                              ║"
      echo "╚══════════════════════════════════════════════════════════════╝"
      echo ""
      exit 1
    fi

    log "Successfully installed:$MISSING_DEPS"
  fi
}

# -----------------------------------------------------------------------------
# Parse arguments
# -----------------------------------------------------------------------------
YES=false
ARGS=""
for arg in "$@"; do
  case "$arg" in
    --yes) YES=true ;;
    *) ARGS="${ARGS} $arg" ;;
  esac
done
set -- $ARGS

# -----------------------------------------------------------------------------
# Confirm before proceeding
# -----------------------------------------------------------------------------
echo ""
echo "╔══════════════════════════════════════════════════════════════╗"
echo "║  epc670_setup_desktop                                        ║"
echo "║                                                              ║"
echo "║  This script will make the following changes:                ║"
echo "║                                                              ║"
echo "║  • Add the user to the epc670 group                          ║"
echo "║  • Install epc670 autostart entries in ~/.config/autostart   ║"
echo "║  • Back up and replace waybar config in ~/.config/waybar     ║"
echo "║  • Back up and replace labwc autostart in ~/.config/labwc    ║"
echo "║  • Create epc670 shortcuts on ~/Desktop                      ║"
echo "║  • Append the epc670 venv block to ~/.bashrc                 ║"
echo "║  • Enable autoresolution                                     ║"

if [ -n "$MISSING_DEPS" ]; then
echo "║                                                              ║"
echo "║  ⚠ The following packages are not installed and will be      ║"
echo "║    installed automatically before setup continues:           ║"
for dep in $MISSING_DEPS; do
printf "║    %-60s║\n" "• $dep"
done
fi

echo "║                                                              ║"
echo "║  Existing waybar and labwc config files will be backed up    ║"
echo "║  to /usr/share/epc670-tofhat-utils/backups/<user>/           ║"
echo "║  and can be restored by running epc670-reset-desktop.        ║"
echo "╚══════════════════════════════════════════════════════════════╝"
echo ""
if [ "$YES" = true ]; then
  log "Proceeding non-interactively (--yes)"
else
  printf "Proceed? [y/N] "
  read -r answer
  case "$answer" in
    y|Y) ;;
    *) log "Aborted by user."; exit 0 ;;
  esac
fi

# -----------------------------------------------------------------------------
# Install missing dependencies after confirmation
# -----------------------------------------------------------------------------
install_missing_deps

# -----------------------------------------------------------------------------
# apply_user_setup <user>
# -----------------------------------------------------------------------------
apply_user_setup() {
  user="$1"
  user_home=$(getent passwd "$user" | cut -d: -f6)
  backup_dir="$BACKUP_BASE/$user"

  # Group membership
  usermod -aG "$VENV_GROUP" "$user"
  log "Added $user to group $VENV_GROUP"

  # Autostart entries
  autostart_dir="$user_home/.config/autostart"
  mkdir -p "$autostart_dir"
  for autostart_desktop in $AUTOSTART_DESKTOPS; do
    cp "/usr/share/applications/$autostart_desktop" "$autostart_dir/$autostart_desktop"
    log "Created autostart entry: $autostart_desktop"
  done
  chown -R "$user:$user" "$autostart_dir"

  # Waybar config — back up existing files before overwriting
  mkdir -p "$user_home/.config/waybar"
  mkdir -p "$backup_dir/waybar"
  for f in $WAYBAR_FILES; do
    src="$user_home/.config/waybar/$f"
    if [ -f "$src" ]; then
      cp "$src" "$backup_dir/waybar/$f"
      log "Backed up $src to $backup_dir/waybar/$f"
    fi
  done
  cp -r "$DOT_CONFIG_WAYBAR/." "$user_home/.config/waybar/"
  chown -R "$user:$user" "$user_home/.config/waybar"

  # Kill and restart waybar to pick up the new config
  REAL_UID=$(id -u "$user")
  if pgrep -u "$user" waybar > /dev/null 2>&1; then
    pkill -u "$user" waybar 2>/dev/null || true
    log "Killed running waybar for $user"
  fi
  XDG_RUNTIME_DIR="/run/user/$REAL_UID" \
    su -c "waybar &" "$user" 2>/dev/null \
    || log "Warning: could not start waybar (session may not be running yet)"
  log "Started waybar for $user"

  # Labwc autostart — back up existing file before overwriting
  mkdir -p "$user_home/.config/labwc"
  mkdir -p "$backup_dir/labwc"
  labwc_dst="$user_home/.config/labwc/autostart"
  if [ -f "$labwc_dst" ]; then
    cp "$labwc_dst" "$backup_dir/labwc/autostart"
    log "Backed up $labwc_dst to $backup_dir/labwc/autostart"
  fi
  cp "$DOT_CONFIG_LABWC" "$labwc_dst"
  chown -R "$user:$user" "$user_home/.config/labwc"

  # Desktop symlinks
  desktop_dir="$user_home/Desktop"
  mkdir -p "$desktop_dir"
  for desktop in $DESKTOP_SYMLINKS; do
    ln -sf "/usr/share/applications/$desktop" "$desktop_dir/$desktop"
    chown -h "$user:$user" "$desktop_dir/$desktop"
    log "Created desktop symlink: $desktop"
  done

  # Bashrc venv block
  touch "$user_home/.bashrc"
  chown "$user:$user" "$user_home/.bashrc"
  "$BASHRC_APPEND" "$user_home/.bashrc" \
    || log "Warning: could not append venv block to .bashrc"

  log "User setup applied for $user"
}

# -----------------------------------------------------------------------------
# Resolve target user
# -----------------------------------------------------------------------------
TARGET_USER="${1:-}"

if [ -z "$TARGET_USER" ]; then
  TARGET_USER="${SUDO_USER:-}"
fi

if [ -z "$TARGET_USER" ] && [ -f "$USERS_CONF" ]; then
  TARGET_USER="$(head -n1 "$USERS_CONF")"
fi

if [ -z "$TARGET_USER" ]; then
  TARGET_USER="epc"
  log "Warning: could not determine target user, falling back to epc"
fi

log "Running desktop setup for: $TARGET_USER"

# -----------------------------------------------------------------------------
# Apply setup for target user
# -----------------------------------------------------------------------------
if id "$TARGET_USER" >/dev/null 2>&1; then
  apply_user_setup "$TARGET_USER"

  # Record user in users.conf
  mkdir -p "$(dirname "$USERS_CONF")"
  if ! grep -qx "$TARGET_USER" "$USERS_CONF" 2>/dev/null; then
    echo "$TARGET_USER" >> "$USERS_CONF"
    log "Recorded $TARGET_USER in $USERS_CONF"
  fi
else
  log "Warning: user $TARGET_USER not found, skipping."
fi

# -----------------------------------------------------------------------------
# Re-apply for any previously recorded users
# -----------------------------------------------------------------------------
if [ -f "$USERS_CONF" ]; then
  while IFS= read -r user; do
    [ -n "$user" ] || continue
    [ "$user" = "$TARGET_USER" ] && continue
    if id "$user" >/dev/null 2>&1; then
      log "Re-applying setup for previously recorded user: $user"
      apply_user_setup "$user"
    fi
  done < "$USERS_CONF"
fi

# -----------------------------------------------------------------------------
# Enable autoresolution
# -----------------------------------------------------------------------------
if is_live_system; then
  epc670-enable-autoresolution \
    && log "Autoresolution enabled." \
    || log "Warning: epc670-enable-autoresolution failed."
fi

# -----------------------------------------------------------------------------
# Record that desktop setup is active.
# Consumed by postinst (to decide whether to re-run setup on upgrade) and
# removed by epc670-reset-desktop once the last recorded user is reset.
# Mirrors users.conf: present iff at least one user is set up.
# -----------------------------------------------------------------------------
if [ -s "$USERS_CONF" ]; then
  mkdir -p "$(dirname "$DESKTOP_STAMP")"
  touch "$DESKTOP_STAMP" \
    && log "Recorded desktop-setup stamp: $DESKTOP_STAMP" \
    || log "Warning: could not write desktop-setup stamp: $DESKTOP_STAMP"
fi

log "Desktop setup complete."
