#!/usr/bin/env bash
set -euo pipefail

readonly REPOSITORY_URL="https://packages.nebulacoder.com/apt"
readonly KEY_URL="${REPOSITORY_URL}/nebula-archive-keyring.gpg"
readonly KEYRING_PATH="/usr/share/keyrings/nebula-archive-keyring.gpg"
readonly SOURCE_PATH="/etc/apt/sources.list.d/nebula.sources"
readonly EXPECTED_FINGERPRINT="OFFLINE_OWNER_KEY_REQUIRED"
readonly BOOTSTRAP_URL_AMD64="https://nebulacoder.com/cli/bootstrap/nebula-cli_1.5.2-1_amd64.deb"
readonly BOOTSTRAP_SHA256_AMD64="edbdbe750369b41531bc11ffa162e31e58b23863b53e2f0c51cb77b2be7b787b"
readonly BOOTSTRAP_URL_ARM64="https://nebulacoder.com/cli/bootstrap/nebula-cli_1.5.2-1_arm64.deb"
readonly BOOTSTRAP_SHA256_ARM64="BOOTSTRAP_ARTIFACT_UNAVAILABLE"
readonly EXPECTED_VERSION="1.5.2"

fail() {
  echo "Nebula CLI installation failed: $*" >&2
  exit 1
}

if [[ "${EUID}" -ne 0 ]]; then
  fail "run this downloaded installer with sudo."
fi

if [[ ! -r /etc/os-release ]]; then
  fail "Debian or Ubuntu is required."
fi

# shellcheck disable=SC1091
source /etc/os-release
case " ${ID:-} ${ID_LIKE:-} " in
  *" debian "*|*" ubuntu "*) ;;
  *) fail "Debian or Ubuntu is required." ;;
esac

command -v dpkg >/dev/null 2>&1 || fail "dpkg is required."
architecture="$(dpkg --print-architecture)"
[[ "${architecture}" == "amd64" || "${architecture}" == "arm64" ]] ||
  fail "Nebula CLI 1.5.2 supports amd64 and arm64."
if [[ "${architecture}" == "amd64" ]]; then
  bootstrap_url="${BOOTSTRAP_URL_AMD64}"
  bootstrap_sha256="${BOOTSTRAP_SHA256_AMD64}"
else
  bootstrap_url="${BOOTSTRAP_URL_ARM64}"
  bootstrap_sha256="${BOOTSTRAP_SHA256_ARM64}"
fi
command -v apt-get >/dev/null 2>&1 || fail "apt-get is required."
command -v curl >/dev/null 2>&1 || fail "curl is required."
temporary="$(mktemp -d)"
trap 'rm -rf -- "${temporary}"' EXIT
downloaded_key="${temporary}/nebula-archive-keyring.gpg"
source_file="${temporary}/nebula.sources"

if [[ "${EXPECTED_FINGERPRINT}" =~ ^[A-F0-9]{40}$ ]]; then
  command -v gpg >/dev/null 2>&1 || fail "gpg is required to verify the repository key."
  curl --fail --silent --show-error --location \
    --proto '=https' --tlsv1.2 \
    "${KEY_URL}" --output "${downloaded_key}"
  actual_fingerprint="$(
    gpg --batch --show-keys --with-colons "${downloaded_key}" 2>/dev/null |
      awk -F: '$1 == "fpr" { print toupper($10); exit }'
  )"
  [[ "${actual_fingerprint}" == "${EXPECTED_FINGERPRINT}" ]] ||
    fail "the downloaded repository key fingerprint does not match the release contract."
  cat >"${source_file}" <<EOF
Types: deb
URIs: ${REPOSITORY_URL}
Suites: stable
Components: main
Architectures: ${architecture}
Signed-By: ${KEYRING_PATH}
EOF
  install -o root -g root -m 0644 "${downloaded_key}" "${KEYRING_PATH}"
  install -o root -g root -m 0644 "${source_file}" "${SOURCE_PATH}"
  apt-get update
  DEBIAN_FRONTEND=noninteractive apt-get install -y nebula-cli
else
  [[ "${bootstrap_sha256}" =~ ^[a-f0-9]{64}$ ]] ||
    fail "the checksum-pinned Nebula CLI bootstrap is unavailable for ${architecture}."
  bootstrap_deb="${temporary}/nebula-cli.deb"
  curl --fail --silent --show-error --location \
    --proto '=https' --tlsv1.2 \
    "${bootstrap_url}" --output "${bootstrap_deb}"
  actual_sha256="$(sha256sum "${bootstrap_deb}" | awk '{print $1}')"
  [[ "${actual_sha256}" == "${bootstrap_sha256}" ]] ||
    fail "the downloaded bootstrap package checksum does not match the release contract."
  DEBIAN_FRONTEND=noninteractive apt-get install -y "${bootstrap_deb}"
fi

installed_version="$(nebula --version 2>&1 || true)"
[[ "${installed_version}" == *"${EXPECTED_VERSION}"* ]] ||
  fail "the installed command did not report Nebula CLI ${EXPECTED_VERSION}."

echo
echo "Nebula CLI installed!"
if [[ "${EXPECTED_FINGERPRINT}" =~ ^[A-F0-9]{40}$ ]]; then
  echo "To update, run:"
  echo "  sudo apt update && sudo apt install nebula-cli"
else
  echo "Installed from the checksum-pinned HTTPS bootstrap package."
  echo "Run this installer command again to update until the signed APT channel is published."
fi
