#!/usr/bin/env bash
# install-espanso.sh — Install Espanso (text expander) with Wayland or X11 build.
# Auto-detects session type; falls back to Wayland if unknown.
# Hardened: handles apt temp file permissions, package collisions, and ghost processes.

set -euo pipefail
IFS=$'\n\t'

readonly SCRIPT_NAME="${0##*/}"
DRY_RUN=0
FORCE_VARIANT=""  # "wayland" | "x11"

usage() {
  cat <<EOF
Usage: sudo $SCRIPT_NAME [--dry-run] [--wayland|--x11] [--help]

Installs Espanso from the latest GitHub release. Auto-detects whether to use
the Wayland or X11 build based on the invoking user (SUDO_USER). 
The systemd-user service is registered for that user, not root.

Options:
  --wayland   Force the Wayland build.
  --x11       Force the X11 build.
  --dry-run   Print actions without executing.
  --help, -h  Show this help.
EOF
}

log()  { printf '\033[1;34m[%s]\033[0m %s\n' "${SCRIPT_NAME%.sh}" "$*"; }
warn() { printf '\033[1;33m[%s] WARN:\033[0m %s\n' "${SCRIPT_NAME%.sh}" "$*" >&2; }
die()  { printf '\033[1;31m[%s] ERROR:\033[0m %s\n' "${SCRIPT_NAME%.sh}" "$*" >&2; exit 1; }
run()  { if (( DRY_RUN )); then printf '  DRY-RUN: %s\n' "$*"; else eval "$@"; fi; }
trap 'rc=$?; (( rc )) && printf "\033[1;31m[%s] failed at line %s (exit %d)\033[0m\n" "${SCRIPT_NAME%.sh}" "$LINENO" "$rc" >&2' ERR

while (( $# )); do
  case "$1" in
    --dry-run) DRY_RUN=1 ;;
    --wayland) FORCE_VARIANT=wayland ;;
    --x11)     FORCE_VARIANT=x11 ;;
    -h|--help) usage; exit 0 ;;
    *) die "Unknown argument: $1 (try --help)" ;;
  esac
  shift
done

(( EUID == 0 )) || die "Must run as root. Try: sudo $SCRIPT_NAME"

[[ -r /etc/os-release ]] || die "/etc/os-release not found."
# shellcheck disable=SC1091
. /etc/os-release
case "${ID:-}:${ID_LIKE:-}" in
  *ubuntu*|*debian*) : ;;
  *) die "Unsupported distro: ${PRETTY_NAME:-unknown}." ;;
esac

ARCH="$(dpkg --print-architecture)"
[[ "$ARCH" == "amd64" ]] || die "Espanso .deb is published for amd64 only (detected: $ARCH)."

ACTUAL_USER="${SUDO_USER:-${USER:-}}"
[[ -n "$ACTUAL_USER" && "$ACTUAL_USER" != "root" ]] || die "Run via sudo as a regular user; cannot register the service as root."
USER_ID="$(id -u "$ACTUAL_USER")"

# --- FIXED: Better session detection logic using loginctl ---
if [[ -n "$FORCE_VARIANT" ]]; then
  VARIANT="$FORCE_VARIANT"
else
  # 1. Try systemd loginctl (most reliable)
  SESSION_ID=$(loginctl list-sessions 2>/dev/null | grep " $ACTUAL_USER " | awk '{print $1}' | head -n 1 || true)
  if [[ -n "$SESSION_ID" ]]; then
    SESSION_TYPE=$(loginctl show-session "$SESSION_ID" -p Type --value 2>/dev/null || true)
  else
    SESSION_TYPE=""
  fi

  # 2. If loginctl fails, check for active Wayland/X11 socket files
  if [[ -z "$SESSION_TYPE" || "$SESSION_TYPE" == "tty" ]]; then
    if sudo -u "$ACTUAL_USER" test -S "/run/user/$USER_ID/wayland-0"; then
      SESSION_TYPE="wayland"
    elif sudo -u "$ACTUAL_USER" test -S "/tmp/.X11-unix/X0"; then
      SESSION_TYPE="x11"
    else
      SESSION_TYPE="wayland" # Default fallback for modern Ubuntu
    fi
  fi

  case "$SESSION_TYPE" in
    wayland) VARIANT=wayland ;;
    x11) VARIANT=x11 ;;
    *) warn "Unknown session type='$SESSION_TYPE'; defaulting to wayland."; VARIANT=wayland ;;
  esac
fi
log "Detected: ${PRETTY_NAME:-unknown}, user: $ACTUAL_USER, session: $VARIANT"

export DEBIAN_FRONTEND=noninteractive

# --- FIXED: Use a subdirectory to avoid apt "unsandboxed" permission warnings ---
WORK_DIR="$(mktemp -d /tmp/espanso-install.XXXXXX)"
chmod 755 "$WORK_DIR"
TEMP_DEB="$WORK_DIR/espanso.deb"
trap 'rm -rf "$WORK_DIR"' EXIT

DEB_NAME="espanso-debian-${VARIANT}-amd64.deb"
URL="https://github.com/espanso/espanso/releases/latest/download/${DEB_NAME}"

log "Installing prerequisites..."
run "apt-get update -qq"
run "apt-get install -y wget libcap2-bin psmisc"

# --- FIXED: Use wget with progress bar instead of silent mode ---
log "Downloading ${DEB_NAME}..."
run "wget -q --show-progress -O '$TEMP_DEB' '$URL'"

log "Removing conflicting Espanso packages (if any)..."
run "apt-get remove -y espanso espanso-wayland >/dev/null 2>&1 || true"

log "Installing package..."
run "apt-get install -y '$TEMP_DEB'"

ESPANSO_BIN="$(command -v espanso || true)"
[[ -x "$ESPANSO_BIN" ]] || die "espanso binary not found after install."

if [[ "$VARIANT" == "wayland" ]]; then
  log "Setting CAP_DAC_OVERRIDE on $ESPANSO_BIN..."
  run "setcap 'cap_dac_override+p' '$ESPANSO_BIN'"
fi

log "Clearing ghost processes to prevent start timeouts..."
run "sudo -u '$ACTUAL_USER' killall espanso 2>/dev/null || true"

log "Registering & starting espanso service for $ACTUAL_USER..."
if (( DRY_RUN )); then
  printf '  DRY-RUN: sudo -u %s XDG_RUNTIME_DIR=/run/user/%s espanso service register || true\n' "$ACTUAL_USER" "$USER_ID"
  printf '  DRY-RUN: sudo -u %s XDG_RUNTIME_DIR=/run/user/%s espanso start || true\n' "$ACTUAL_USER" "$USER_ID"
else
  sudo -u "$ACTUAL_USER" XDG_RUNTIME_DIR="/run/user/$USER_ID" espanso service register || true
  sudo -u "$ACTUAL_USER" XDG_RUNTIME_DIR="/run/user/$USER_ID" espanso restart || \
    sudo -u "$ACTUAL_USER" XDG_RUNTIME_DIR="/run/user/$USER_ID" espanso start || true
fi

log "Done. Espanso ($VARIANT) installed and started for $ACTUAL_USER."
if [[ "$VARIANT" == "wayland" ]]; then
  log "Wayland note: non-US keyboards must set the layout in ~/.config/espanso/config/default.yml"
fi