#!/usr/bin/env bash
# Interactive Desk — one-time installation script
# Run manually after Ubuntu Server 24.04 LTS minimal install.
# Bootstrap internet: Android USB tethering or USB WiFi dongle
set -euo pipefail

DESK_USER="${SUDO_USER:-$USER}"
BASE_URL="${BASE_URL:-https://j2mef.zereb.net/desktop-kiosk/}"

if [ "$DESK_USER" != "desk" ]; then
    echo "WARNING: User is '$DESK_USER', not 'desk'."
    echo "The niri config hardcodes paths for /home/desk/jar/ and /home/desk."
    echo "Either symlink /home/desk -> /home/$DESK_USER or edit config.kdl after install."
    echo ""
fi

# --- Passwordless sudo for this script ---
echo ""
echo ">>> Setting up passwordless sudo for installation commands..."
SUDOERS_FILE="/etc/sudoers.d/desk-install"
if [ ! -f "$SUDOERS_FILE" ]; then
  sudo tee "$SUDOERS_FILE" > /dev/null <<SUDOERS
# Allow passwordless execution of commands needed by install.sh
$DESK_USER ALL=(ALL) NOPASSWD: /usr/bin/apt, /usr/bin/tee, /usr/sbin/usermod, /usr/bin/loginctl, /bin/mkdir, /bin/cp
$DESK_USER ALL=($DESK_USER) NOPASSWD: /usr/bin/bash
SUDOERS
  sudo chmod 0440 "$SUDOERS_FILE"
fi

echo "=== Interactive Desk Setup ==="
echo "User: $DESK_USER"

# --- Pre-flight: verify all remote files exist ---
echo ""
echo ">>> Checking all remote files are available..."
REMOTE_FILES=(
  "config.kdl"
  "desk-display.jar" "desk-map.jar" "desk-launcher.jar" "desk-voice.jar"
  "desk-voice.service" "desk-display.service" "desk-map.service" "desk-launcher.service"
  "docker-compose.yml"
)
MISSING=0
for f in "${REMOTE_FILES[@]}"; do
  if ! curl --head --silent --fail "$BASE_URL/$f" > /dev/null 2>&1; then
    echo "  MISSING: $BASE_URL/$f"
    MISSING=1
  else
    echo "  OK: $f"
  fi
done
if [ "$MISSING" -eq 1 ]; then
  echo "ERROR: One or more required files are missing on the server. Aborting."
  exit 1
fi

# --- System packages ---
echo ""
echo ">>> Installing system packages..."
if [ -f "$HOME/.kiosk-packages-installed" ]; then
  echo "  Package marker found, skipping apt install."
else
  sudo apt update
  sudo apt install -y \
      docker.io docker-compose-v2 \
      pipewire-pulse wireplumber \
      vulkan-tools mesa-vulkan-drivers \
      openjdk-21-jre-headless \
      curl git wget \
      alsa-utils \
      lisgd \
      gcc clang libudev-dev libgbm-dev libxkbcommon-dev libegl1-mesa-dev \
      libwayland-dev libinput-dev libdbus-1-dev libsystemd-dev \
      libseat-dev libpipewire-0.3-dev libpango1.0-dev libdisplay-info-dev \
      network-manager-gnome pavucontrol
  touch "$HOME/.kiosk-packages-installed"

# --- Docker group ---
echo ""
echo ">>> Adding user to docker group..."
sudo usermod -aG docker "$DESK_USER"

# --- input group (for reading /dev/input/event* touch devices) ---
echo ""
echo ">>> Adding user to input group..."
sudo usermod -aG input "$DESK_USER"

# --- audio group (for ALSA microphone access) ---
echo ""
echo ">>> Adding user to audio group..."
sudo usermod -aG audio "$DESK_USER"


# --- Autologin on tty1 ---
echo ""
echo ">>> Configuring autologin on tty1..."
sudo mkdir -p /etc/systemd/system/getty@tty1.service.d
sudo tee /etc/systemd/system/getty@tty1.service.d/override.conf > /dev/null <<EOF
[Service]
ExecStart=
ExecStart=-/sbin/agetty --autologin $DESK_USER --noclear %I \$TERM
EOF

# --- Rust toolchain (for building niri) ---
echo ""
echo ">>> Installing Rust toolchain..."
sudo -u "$DESK_USER" bash -c "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y" 2>&1
fi

# --- PipeWire echo-cancel (prevents assistant from hearing own voice) ---
# Runs every time (outside the apt guard) so re-running install.sh updates it.
echo ""
echo ">>> Configuring PipeWire echo cancellation..."
sudo mkdir -p /etc/pipewire/pipewire.conf.d
sudo tee /etc/pipewire/pipewire.conf.d/60-echo-cancel.conf > /dev/null <<'PWCONF'
context.modules = [
  {
    name = libpipewire-module-echo-cancel
    args = {
      monitor.mode = true
      # Onboard mic + SVEN USB speaker are on different ALSA cards — pin explicitly
      source = "alsa_input.pci-0000_00_14.2.pro-input-0"
      sink   = "alsa_output.usb-Jieli_Technology_SVEN_SB-G1400-01.analog-stereo"
      capture.props = {
        node.name = "ec_capture_in"
        node.description = "Echo-cancel capture"
        node.passive = true
      }
      source.props = {
        node.name = "source_ec"
        node.description = "Echo-cancelled microphone"
        media.name = "Echo-cancelled microphone"
        media.class = "Audio/Source"
      }
      aec.args = {
        webrtc.gain_control = false
        webrtc.extended_filter = true
        webrtc.noise_suppression = true
      }
    }
  }
]
PWCONF
# Restart PipeWire to pick up the new config (harmless if not running yet)
DESK_UID=$(id -u "$DESK_USER" 2>/dev/null || echo 1000)
XDG_RUNTIME_DIR="/run/user/$DESK_UID" systemctl --user restart pipewire-pulse.service 2>/dev/null || true

# --- Build and install niri from source ---
if command -v niri &>/dev/null; then
  echo ""
  echo ">>> niri already installed ($(niri --version)), skipping build."
else
  echo ""
  echo ">>> Building niri from source (takes ~2-3 min)..."
  sudo -u "$DESK_USER" bash -c '
  export PATH="$HOME/.cargo/bin:$PATH"
  cd /tmp
  git clone --depth 1 --branch v26.04 https://github.com/niri-wm/niri.git
  cd niri
  cargo build --release
  ' 2>&1

  echo ">>> Installing niri binaries..."
  sudo cp /tmp/niri/target/release/niri /usr/local/bin/niri
  sudo cp /tmp/niri/resources/niri-session /usr/local/bin/niri-session
  sudo mkdir -p /usr/local/share/wayland-sessions
  sudo cp /tmp/niri/resources/niri.desktop /usr/local/share/wayland-sessions/niri.desktop
  sudo mkdir -p /etc/systemd/user /usr/local/share/xdg-desktop-portal
  sudo cp /tmp/niri/resources/niri.service /etc/systemd/user/niri.service
  sudo cp /tmp/niri/resources/niri-shutdown.target /etc/systemd/user/niri-shutdown.target
  sudo cp /tmp/niri/resources/niri-portals.conf /usr/local/share/xdg-desktop-portal/niri-portals.conf
  rm -rf /tmp/niri
fi

# --- Niri config ---
echo ""
echo ">>> Downloading Niri config..."
mkdir -p "$HOME/.config/niri"
wget --no-check-certificate -O "$HOME/.config/niri/config.kdl" "$BASE_URL/config.kdl"
echo "  IMPORTANT: Edit ~/.config/niri/config.kdl to set your display output name."
echo "  Run 'wlr-randr' after first boot to find it."

# --- Auto-update + niri auto-launch in .bashrc ---
echo ""
echo ">>> Adding auto-update and niri auto-launch to .bashrc..."
if ! grep -q "niri-session" "$HOME/.bashrc" 2>/dev/null; then
    cat >> "$HOME/.bashrc" << 'BASHRC'

# Auto-launch niri Wayland compositor on tty1
if [ "$(tty)" = "/dev/tty1" ] && [ -z "$WAYLAND_DISPLAY" ] && [ -z "$DISPLAY" ]; then
    # Retry until PipeWire registers the echo-cancelled source and SVEN sink
    for i in 1 2 3 4 5; do
        if pactl list sources short 2>/dev/null | grep -q source_ec; then
            pactl set-default-source source_ec
        fi
        if pactl list sinks short 2>/dev/null | grep -q 'SB-G1400'; then
            pactl set-default-sink alsa_output.usb-Jieli_Technology_SVEN_SB-G1400-01.analog-stereo
        fi
        if pactl list sources short 2>/dev/null | grep -q source_ec \
            && pactl list sinks short 2>/dev/null | grep -q 'SB-G1400'; then
            break
        fi
        sleep 1
    done
    exec niri-session
fi
BASHRC
fi

# --- Download fatJars and app service files ---
echo ""
echo ">>> Downloading fatJars and app services from $BASE_URL..."
FATJAR_DIR="$HOME/jar"
SYSTEMD_DIR="$HOME/.config/systemd/user"
mkdir -p "$FATJAR_DIR"
mkdir -p "$SYSTEMD_DIR"

for f in desk-display.jar desk-map.jar desk-launcher.jar desk-voice.jar; do
  echo "  Downloading $f..."
  wget --no-check-certificate -O "$FATJAR_DIR/$f" "$BASE_URL/$f"
done

for f in desk-voice.service desk-display.service desk-map.service desk-launcher.service; do
  echo "  Downloading $f..."
  wget --no-check-certificate -O "$SYSTEMD_DIR/$f" "$BASE_URL/$f"
done

# --- Download docker-compose.yml ---
echo ""
echo ">>> Downloading docker-compose.yml..."
wget --no-check-certificate -O "$HOME/docker-compose.yml" "$BASE_URL/docker-compose.yml"

# --- Download LLM models ---
echo ""
echo ">>> Downloading LLM models..."
MODELS_DIR="$HOME/models"
mkdir -p "$MODELS_DIR"

for url in \
  "https://huggingface.co/bartowski/Qwen2.5-3B-Instruct-GGUF/resolve/main/Qwen2.5-3B-Instruct-Q4_K_M.gguf" \
  "https://huggingface.co/unsloth/Qwen3.5-4B-GGUF/resolve/main/Qwen3.5-4B-Q6_K.gguf?download=true" \
  "https://huggingface.co/unsloth/Qwen3.5-4B-GGUF/resolve/main/Qwen3.5-4B-Q8_0.gguf?download=true" \
  "https://huggingface.co/unsloth/Qwen3.5-4B-GGUF/resolve/main/Qwen3.5-4B-Q4_K_M.gguf?download=true" ; do
  filename=$(basename "$url" | sed 's/\?download=true//')
  if [ -f "$MODELS_DIR/$filename" ]; then
    echo "  $filename already exists, skipping."
  else
    echo "  Downloading $filename..."
    wget -O "$MODELS_DIR/$filename" "$url"
  fi
done

# --- Enable systemd user services ---
echo ""
echo ">>> Enabling systemd user services..."
sudo loginctl enable-linger "$DESK_USER"
DESK_UID=$(id -u "$DESK_USER")
XDG_RUNTIME_DIR="/run/user/$DESK_UID" systemctl --user daemon-reload
XDG_RUNTIME_DIR="/run/user/$DESK_UID" systemctl --user enable desk-voice.service

# --- Start Docker containers ---
echo ""
echo ">>> Starting Docker containers..."
sg docker -c "docker compose -f '$HOME/docker-compose.yml' up -d"
killall java

echo ""
echo "=== Installation complete ==="
echo ""
echo "Post-install steps:"
echo "  1. After reboot, edit ~/.config/niri/config.kdl — set output name from 'wlr-randr'"
echo "  2. Run 'sudo loginctl terminate-user $USER' at another tty to force niri to start (or reboot)"
echo "  3. The system will auto-login on tty1 → bashrc launches niri-session → niri starts systemd services."
echo ""
