#!/usr/bin/env bash
# MspCoreX RMM Agent — Linux installer
# Published at https://apt.mspcorex.com/install
#
# WARNING: running any script via `curl | sudo bash` requires trust in the
# publishing host. Verify HTTPS + the GPG fingerprint printed below before use.
set -euo pipefail

ARCHIVE_URL="https://apt.mspcorex.com"
KEY_URL="${ARCHIVE_URL}/mspcorex-apt-key.gpg"
SOURCES_FILE="/etc/apt/sources.list.d/mspcorex.list"
KEYRING_FILE="/usr/share/keyrings/mspcorex.gpg"
# Stable-only since 2026-06-10 — canary/beta channels are retired.
CHANNEL="stable"

# === Hard-coded fingerprint of the MspCoreX offline signing key. ===
# This is the *out-of-band* trust anchor. The key file fetched over HTTPS
# from $KEY_URL is verified against this fingerprint before sources.list is
# written and before any package is installed.
#
# TODO[operator-ceremony]: replace the placeholder with the real fingerprint
# recorded during the GPG ceremony (see docs/operator/gpg-ceremony.md).
PINNED_FPR="${PINNED_FPR:-REPLACE_WITH_REAL_FINGERPRINT_FROM_CEREMONY}"
EXPECTED_FPR="${MSPCOREX_EXPECTED_FPR:-$PINNED_FPR}"

red()   { printf '\033[0;31m%s\033[0m\n' "$*"; }
green() { printf '\033[0;32m%s\033[0m\n' "$*"; }
blue()  { printf '\033[0;34m%s\033[0m\n' "$*"; }

require_root() {
  if [ "$(id -u)" -ne 0 ]; then
    red "ERROR: this installer must be run as root (try: curl ... | sudo bash)"
    exit 1
  fi
}

require_cmd() {
  for c in "$@"; do
    if ! command -v "$c" >/dev/null 2>&1; then
      red "ERROR: missing required command: $c"
      exit 1
    fi
  done
}

detect_distro() {
  if [ ! -r /etc/os-release ]; then
    red "ERROR: /etc/os-release missing — cannot detect distribution"
    exit 1
  fi
  # shellcheck disable=SC1091
  . /etc/os-release
  case "$ID" in
    debian|ubuntu|raspbian) ;;
    *)
      red "ERROR: unsupported distribution: $ID"
      red "Supported: debian, ubuntu, raspbian"
      exit 1
      ;;
  esac
  blue "Detected: $PRETTY_NAME"
}

reject_retired_channels() {
  # Catch stale automation still exporting MSPCOREX_CHANNEL: anything other
  # than "stable" (or unset) is a hard error, not a silent override.
  if [ -n "${MSPCOREX_CHANNEL:-}" ] && [ "${MSPCOREX_CHANNEL}" != "stable" ]; then
    red "ERROR: MSPCOREX_CHANNEL='${MSPCOREX_CHANNEL}' — canary/beta channels were retired on 2026-06-10."
    red "       The agent installs from the single 'stable' channel; unset MSPCOREX_CHANNEL."
    exit 1
  fi
  blue "Channel: stable"
}

import_key() {
  blue "Importing MspCoreX archive signing key..."
  mkdir -p "$(dirname "$KEYRING_FILE")"

  # Download to a tmp file first so we can verify before installing.
  local tmpdir
  tmpdir="$(mktemp -d)"
  trap 'rm -rf "$tmpdir"' EXIT
  if ! curl -fsSL --max-time 60 "$KEY_URL" -o "$tmpdir/key.asc"; then
    red "ERROR: failed to download $KEY_URL"; exit 2
  fi
  if [ ! -s "$tmpdir/key.asc" ]; then
    red "ERROR: empty key file from $KEY_URL"; exit 2
  fi
  if ! gpg --dearmor --yes -o "$tmpdir/key.gpg" < "$tmpdir/key.asc"; then
    red "ERROR: gpg --dearmor failed"; exit 2
  fi

  local actual_fpr
  actual_fpr="$(gpg --no-default-keyring --keyring "$tmpdir/key.gpg" \
    --list-keys --with-colons --with-fingerprint \
    | awk -F: '/^fpr:/ {print $10; exit}')"
  if [ -z "$actual_fpr" ]; then
    red "ERROR: could not read fingerprint from downloaded key"; exit 2
  fi

  if [ "$EXPECTED_FPR" = "REPLACE_WITH_REAL_FINGERPRINT_FROM_CEREMONY" ]; then
    red "ERROR: this installer is shipping the placeholder fingerprint."
    red "        Replace PINNED_FPR with the real value from the GPG ceremony."
    red "        See docs/operator/gpg-ceremony.md."
    exit 3
  fi
  if [ "$actual_fpr" != "$EXPECTED_FPR" ]; then
    red "ERROR: fingerprint mismatch — refusing to install."
    red "  expected: $EXPECTED_FPR"
    red "  got:      $actual_fpr"
    red "If you are intentionally adopting a new signing key, set"
    red "  MSPCOREX_EXPECTED_FPR=<new-fpr>"
    red "explicitly. Otherwise this is a SUPPLY-CHAIN ALERT — do not proceed."
    exit 2
  fi

  green "Verified fingerprint: $actual_fpr"
  install -m 0644 "$tmpdir/key.gpg" "$KEYRING_FILE"
}

write_sources() {
  blue "Writing $SOURCES_FILE..."
  cat > "$SOURCES_FILE" <<EOF
# MspCoreX RMM agent — $CHANNEL channel
deb [signed-by=$KEYRING_FILE] $ARCHIVE_URL/ $CHANNEL main
EOF
  chmod 0644 "$SOURCES_FILE"
}

install_package() {
  blue "Running apt-get update..."
  apt-get update -qq

  blue "Installing mspcorex-agent..."
  DEBIAN_FRONTEND=noninteractive apt-get install -y -qq mspcorex-agent
}

print_next_steps() {
  cat <<MSG

$(green "MspCoreX RMM agent installed.")

To enroll this machine, run:

  sudo mspcorex-agent enroll --code <CODE> --server https://app.mspcorex.com

The 6-character code is generated by your MSP administrator in the
MspCoreX portal under the client's devices page.

Verify service status any time with:

  systemctl status mspcorex-agent
  mspcorex-agent self-test

Docs: https://docs.mspcorex.com/agent/linux
Support: support@mspcorex.com
MSG
}

main() {
  require_root
  require_cmd curl gpg apt-get
  detect_distro
  reject_retired_channels
  import_key
  write_sources
  install_package
  print_next_steps
}

main "$@"
