#!/usr/bin/env bash

set -euo pipefail

# Nilo Linux Runner installer
# Usage: curl -sfL https://downloads.nilo-assistant.com/nilo-runner/linux/latest/install.sh | sudo bash

BINARY_NAME="nilo-runner-linux"
INSTALL_DIR="/usr/local/bin"
DEFAULT_REMOTE_URL="https://app.nilo-assistant.com"
DOWNLOAD_BASE_URL="https://downloads.nilo-assistant.com/nilo-runner/linux/latest"

log_info() {
  echo "[INFO] $*"
}

log_error() {
  echo "[ERROR] $*" >&2
}

detect_arch() {
  local arch
  arch=$(uname -m)
  case "$arch" in
    x86_64)
      echo "amd64"
      ;;
    aarch64|arm64)
      echo "arm64"
      ;;
    *)
      log_error "Unsupported architecture: $arch"
      exit 1
      ;;
  esac
}

download_binary() {
  local url="$1"
  local output="$2"

  log_info "Downloading binary from $url"

  if command -v curl >/dev/null 2>&1; then
    curl -fsSL --retry 3 -o "$output" "$url"
  elif command -v wget >/dev/null 2>&1; then
    wget -q --tries=3 -O "$output" "$url"
  else
    log_error "Neither curl nor wget is available"
    exit 1
  fi
}

get_binary_url() {
  local arch="$1"
  echo "${DOWNLOAD_BASE_URL}/${BINARY_NAME}-${arch}"
}

prompt_required() {
  local prompt_text="$1"
  local value=""
  while [[ -z "$value" ]]; do
    if ! IFS= read -r -p "$prompt_text" value </dev/tty; then
      log_error "The installer needs an interactive terminal to read setup values."
      exit 1
    fi
    value=$(echo "$value" | xargs)
    if [[ -z "$value" ]]; then
      echo "This field is required. Please try again." >&2
    fi
  done
  echo "$value"
}

prompt_optional() {
  local prompt_text="$1"
  local default_value="${2:-}"
  local value
  if ! IFS= read -r -p "$prompt_text" value </dev/tty; then
    log_error "The installer needs an interactive terminal to read setup values."
    exit 1
  fi
  value=$(echo "$value" | xargs)
  if [[ -z "$value" && -n "$default_value" ]]; then
    echo "$default_value"
  else
    echo "$value"
  fi
}

# --- Main ---

if [[ "$EUID" -ne 0 ]]; then
  log_error "This script must be run as root (use sudo)"
  exit 1
fi

echo ""
echo "=== Nilo Linux Runner Installation ==="
echo ""

REMOTE_URL=$(prompt_optional "Remote Nilo base URL [$DEFAULT_REMOTE_URL]: " "$DEFAULT_REMOTE_URL")
REGISTRATION_KEY=$(prompt_required "Runner registration key: ")
DEVICE_NAME=$(prompt_optional "Device name [$(hostname)]: " "$(hostname)")
RUNNER_USER="${NILO_RUNNER_USER:-${SUDO_USER:-}}"
if [[ -z "$RUNNER_USER" ]]; then
  RUNNER_USER=$(prompt_required "Linux account that should run this runner: ")
fi
if ! id -u "$RUNNER_USER" >/dev/null 2>&1; then
  log_error "Linux account does not exist: $RUNNER_USER"
  exit 1
fi
RUNNER_GROUP=$(id -gn "$RUNNER_USER")
RUNNER_HOME=$(getent passwd "$RUNNER_USER" | awk -F: '{print $6}')
RUNNER_SHELL=$(getent passwd "$RUNNER_USER" | awk -F: '{print $7}')
if [[ -z "$RUNNER_HOME" || -z "$RUNNER_SHELL" || ! -x "$RUNNER_SHELL" ]]; then
  log_error "Linux account must have an executable login shell: $RUNNER_USER"
  exit 1
fi
DATA_DIR="$RUNNER_HOME/.local/share/nilo-runner"

echo ""
log_info "Remote URL: $REMOTE_URL"
log_info "Device name: $DEVICE_NAME"
log_info "Runner account: $RUNNER_USER"

ARCH=$(detect_arch)
log_info "Detected architecture: $ARCH"

DOWNLOAD_URL=$(get_binary_url "$ARCH")
log_info "Binary URL: $DOWNLOAD_URL"

TMP_DIR=$(mktemp -d)
trap 'rm -rf "$TMP_DIR"' EXIT

BINARY_PATH="$TMP_DIR/$BINARY_NAME"
download_binary "$DOWNLOAD_URL" "$BINARY_PATH"
chmod +x "$BINARY_PATH"

# Verify binary works
if ! "$BINARY_PATH" --help >/dev/null 2>&1; then
  log_error "Downloaded binary does not appear to be valid"
  exit 1
fi

log_info "Installing Nilo Linux Runner..."

# Install binary
cp "$BINARY_PATH" "$INSTALL_DIR/$BINARY_NAME"
chmod +x "$INSTALL_DIR/$BINARY_NAME"

# Keep runner state in the same account that owns its commands and files.
mkdir -p "$DATA_DIR"
chown "$RUNNER_USER:$RUNNER_GROUP" "$DATA_DIR"
chmod 700 "$DATA_DIR"

# Preserve the existing device identity when upgrading from the former system-user install.
if [[ -f /var/lib/nilo-runner/device-id && ! -f "$DATA_DIR/device-id" ]]; then
  cp /var/lib/nilo-runner/device-id "$DATA_DIR/device-id"
  chown "$RUNNER_USER:$RUNNER_GROUP" "$DATA_DIR/device-id"
  chmod 600 "$DATA_DIR/device-id"
fi
if [[ -f /etc/sudoers.d/nilo-runner ]]; then
  rm /etc/sudoers.d/nilo-runner
  log_info "Removed legacy elevated permissions for the former nilo service account"
fi

# Install systemd service
SERVICE_FILE="/etc/systemd/system/nilo-runner.service"
cat > "$SERVICE_FILE" <<EOF
[Unit]
Description=Nilo Linux Runner
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=${RUNNER_USER}
Group=${RUNNER_GROUP}
ExecStart=${INSTALL_DIR}/${BINARY_NAME}
Restart=always
RestartSec=10
Environment="NILO_RUNNER_REMOTE_URL=${REMOTE_URL}"
Environment="NILO_RUNNER_REGISTRATION_KEY=${REGISTRATION_KEY}"
Environment="NILO_RUNNER_DEVICE_NAME=${DEVICE_NAME}"
Environment="NILO_RUNNER_SHELL=${RUNNER_SHELL}"
Environment="NILO_RUNNER_DATA_DIR=${DATA_DIR}"
Environment="NILO_RUNNER_LOG_LEVEL=info"
Environment="HOME=${RUNNER_HOME}"
Environment="SHELL=${RUNNER_SHELL}"
WorkingDirectory=${RUNNER_HOME}
ReadWritePaths=${DATA_DIR}
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF

chmod 644 "$SERVICE_FILE"

# Reload systemd, then enable and start the service
systemctl daemon-reload
systemctl enable --now nilo-runner.service

echo ""
log_info "Installation complete."
echo ""
echo "The runner service is enabled and running."
echo ""
echo "Check status with:"
echo "  sudo systemctl status nilo-runner"
echo ""
echo "View logs with:"
echo "  sudo journalctl -u nilo-runner -f"
