#!/usr/bin/env bash

set -euo pipefail

SERVICE_USER=agent-insight
RUNTIME_DIR=/var/lib/agent-insight/runtime
PRIVATE_NODE="$RUNTIME_DIR/node"
NODE_PATH_FILE="$RUNTIME_DIR/node-path"
NODE_ORIGIN_FILE="$RUNTIME_DIR/node-origin"
STAGED_NODE="$RUNTIME_DIR/node.candidate"
MIN_NODE_MAJOR=20

info() {
  printf 'agent-insight: %s\n' "$*"
}

warn() {
  printf 'agent-insight: WARNING: %s\n' "$*" >&2
}

node_version() {
  local candidate="$1"
  runuser -u "$SERVICE_USER" -- "$candidate" -p 'process.versions.node' 2>/dev/null
}

node_is_compatible() {
  local candidate="$1"
  local version
  local major

  [ -x "$candidate" ] || return 1
  version="$(node_version "$candidate")" || return 1
  major="${version%%.*}"
  [[ "$major" =~ ^[0-9]+$ ]] || return 1
  [ "$major" -ge "$MIN_NODE_MAJOR" ]
}

record_node() {
  local node_path="$1"
  local node_origin="$2"
  local version

  version="$(node_version "$node_path")"
  printf '%s\n' "$node_path" > "$NODE_PATH_FILE"
  printf '%s\n' "$node_origin" > "$NODE_ORIGIN_FILE"
  chmod 0644 "$NODE_PATH_FILE" "$NODE_ORIGIN_FILE"
  info "using Node.js v$version from $node_origin"
}

install_private_node() {
  local candidate="$1"

  install -m 0755 "$candidate" "$STAGED_NODE" 2>/dev/null || return 1
  chown root:root "$STAGED_NODE"
  if ! node_is_compatible "$STAGED_NODE"; then
    unlink "$STAGED_NODE"
    return 1
  fi
  mv -f "$STAGED_NODE" "$PRIVATE_NODE"
  record_node "$PRIVATE_NODE" "$candidate"
}

install -d -o root -g root -m 0755 "$RUNTIME_DIR"

SYSTEM_CANDIDATES=()
if command -v node >/dev/null 2>&1; then
  SYSTEM_CANDIDATES+=("$(command -v node)")
fi
SYSTEM_CANDIDATES+=(
  /usr/local/bin/node
  /usr/bin/node
  /bin/node
  /opt/node/bin/node
)

for candidate in "${SYSTEM_CANDIDATES[@]}"; do
  if node_is_compatible "$candidate"; then
    record_node "$(readlink -f "$candidate")" "$candidate"
    exit 0
  fi
done

if node_is_compatible "$PRIVATE_NODE"; then
  previous_origin="$PRIVATE_NODE"
  if [ -r "$NODE_ORIGIN_FILE" ]; then
    previous_origin="$(head -n 1 "$NODE_ORIGIN_FILE")"
  fi
  record_node "$PRIVATE_NODE" "$previous_origin"
  exit 0
fi

while IFS= read -r candidate; do
  [ -n "$candidate" ] || continue
  if install_private_node "$candidate"; then
    exit 0
  fi
done < <(
  for nvm_root in /root/.nvm/versions/node /home/*/.nvm/versions/node; do
    [ -d "$nvm_root" ] || continue
    find "$nvm_root" -mindepth 3 -maxdepth 3 -type f -path '*/bin/node' -print
  done | sort -Vr
)

: > "$NODE_PATH_FILE"
chmod 0644 "$NODE_PATH_FILE"
warn "no Node.js >= $MIN_NODE_MAJOR was found"
warn "install Node.js, then run: sudo /usr/libexec/agent-insight-node-setup"
exit 0
