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

BASE_URL="${NOVIJ_CPP_SDK_PACKAGE_BASE_URL:-https://packages.novij.tech/sdk/cpp}"
CHANNEL="${NOVIJ_CPP_SDK_PACKAGE_CHANNEL:-latest}"
PACKAGE_NAME="${NOVIJ_CPP_SDK_PACKAGE_NAME:-libnovij-cpp-sdk-dev}"
ARCH="${NOVIJ_CPP_SDK_PACKAGE_ARCH:-amd64}"
CURRENT_VERSION="0.6.06.210038"
ACTION="check"
NON_INTERACTIVE=0

usage() {
  cat <<'EOF'
Usage:
  novij-cpp-sdk-update check [--base-url URL] [--channel NAME]
  novij-cpp-sdk-update install [--base-url URL] [--channel NAME] [--non-interactive]

Environment:
  NOVIJ_CPP_SDK_PACKAGE_BASE_URL   default package base URL
  NOVIJ_CPP_SDK_PACKAGE_CHANNEL    default channel, usually latest or stable
EOF
}

fetch_stdout() {
  local url="$1"
  if command -v curl >/dev/null 2>&1; then
    curl -fsSL --connect-timeout 10 --max-time 30 "$url"
    return
  fi
  if command -v wget >/dev/null 2>&1; then
    wget -qO- "$url"
    return
  fi
  echo "ERROR: curl or wget is required" >&2
  return 127
}

fetch_file() {
  local url="$1"
  local out="$2"
  if command -v curl >/dev/null 2>&1; then
    curl -fsSL --connect-timeout 10 --max-time 300 "$url" -o "$out"
    return
  fi
  if command -v wget >/dev/null 2>&1; then
    wget -qO "$out" "$url"
    return
  fi
  echo "ERROR: curl or wget is required" >&2
  return 127
}

version_gt() {
  dpkg --compare-versions "$1" gt "$2"
}

installed_version() {
  dpkg-query -W -f='${Version}' "$PACKAGE_NAME" 2>/dev/null || printf '%s' "$CURRENT_VERSION"
}

while [ "$#" -gt 0 ]; do
  case "$1" in
    check|install)
      ACTION="$1"
      shift
      ;;
    --check)
      ACTION="check"
      shift
      ;;
    --install)
      ACTION="install"
      shift
      ;;
    --base-url)
      BASE_URL="${2:?missing --base-url value}"
      shift 2
      ;;
    --channel)
      CHANNEL="${2:?missing --channel value}"
      shift 2
      ;;
    --package-name)
      PACKAGE_NAME="${2:?missing --package-name value}"
      shift 2
      ;;
    --arch)
      ARCH="${2:?missing --arch value}"
      shift 2
      ;;
    --current-version)
      CURRENT_VERSION="${2:?missing --current-version value}"
      shift 2
      ;;
    --non-interactive|-y)
      NON_INTERACTIVE=1
      shift
      ;;
    --help|-h)
      usage
      exit 0
      ;;
    *)
      echo "ERROR: unknown argument: $1" >&2
      usage >&2
      exit 2
      ;;
  esac
done

BASE_URL="${BASE_URL%/}"
PACKAGE_FILE="${PACKAGE_NAME}_${ARCH}.deb"
CURRENT="$(installed_version)"
LATEST="$(fetch_stdout "${BASE_URL}/${CHANNEL}/VERSION" | tr -d '[:space:]')"

if [ -z "$LATEST" ]; then
  echo "ERROR: empty latest version from ${BASE_URL}/${CHANNEL}/VERSION" >&2
  exit 1
fi

if ! version_gt "$LATEST" "$CURRENT"; then
  echo "Novij C++ SDK is up to date: ${CURRENT}"
  exit 0
fi

echo "Novij C++ SDK update available: ${CURRENT} -> ${LATEST}"

if [ "$ACTION" != "install" ]; then
  exit 10
fi

if [ "$NON_INTERACTIVE" != "1" ] && [ ! -t 0 ]; then
  echo "ERROR: non-interactive install requires --non-interactive" >&2
  exit 2
fi

TMP_DIR="/var/tmp/novij-cpp-sdk/update"
install -d -m 0755 "$TMP_DIR"
DEB_PATH="${TMP_DIR}/${PACKAGE_FILE}"
SUMS_PATH="${TMP_DIR}/SHA256SUMS"

fetch_file "${BASE_URL}/${CHANNEL}/${PACKAGE_FILE}" "$DEB_PATH"
fetch_file "${BASE_URL}/${CHANNEL}/SHA256SUMS" "$SUMS_PATH"
chmod 0644 "$DEB_PATH" "$SUMS_PATH"

SUM_LINE="$(grep -F " ${PACKAGE_FILE}" "$SUMS_PATH" | head -n 1 || true)"
if [ -z "$SUM_LINE" ]; then
  echo "ERROR: ${PACKAGE_FILE} is missing from SHA256SUMS" >&2
  exit 1
fi

(cd "$TMP_DIR" && printf '%s\n' "$SUM_LINE" | sha256sum -c -)

if [ "$(id -u)" = "0" ]; then
  apt-get install -y "$DEB_PATH"
else
  sudo apt-get install -y "$DEB_PATH"
fi

echo "Updated Novij C++ SDK to ${LATEST}"
