#!/usr/bin/env bash
#
# Hive headless installer.
#
#   curl -fsSL https://hive.vazac.dev/install.sh | bash
#
# Downloads the `hive` CLI for this machine's OS/architecture from the Hive
# distribution server, verifies its SHA-256 against the published manifest, and
# installs it to /usr/local/bin/hive. The privileged copy step uses `sudo`; the
# rest runs as the invoking user.
#
# After it finishes, run `hive install` yourself to launch the interactive
# daemon setup wizard (it cannot run over a piped stdin).

set -euo pipefail

BASE_URL="${HIVE_BASE_URL:-https://dl.vazac.dev}"
MANIFEST_URL="${BASE_URL}/manifest.json"
INSTALL_DIR="${HIVE_INSTALL_DIR:-/usr/local/bin}"

# --- pretty output ---------------------------------------------------------
if [ -t 1 ]; then
  BOLD=$(printf '\033[1m'); DIM=$(printf '\033[2m'); RED=$(printf '\033[31m')
  GRN=$(printf '\033[32m'); YEL=$(printf '\033[33m'); BLU=$(printf '\033[34m')
  RST=$(printf '\033[0m')
else
  BOLD=""; DIM=""; RED=""; GRN=""; YEL=""; BLU=""; RST=""
fi
say()  { printf '%s\n' "$*"; }
step() { printf '%s==>%s %s\n' "$BLU$BOLD" "$RST" "$*"; }
ok()   { printf '%s  ok%s %s\n' "$GRN" "$RST" "$*"; }
warn() { printf '%s warn%s %s\n' "$YEL" "$RST" "$*" >&2; }
die()  { printf '%serror%s %s\n' "$RED$BOLD" "$RST" "$*" >&2; exit 1; }

need() { command -v "$1" >/dev/null 2>&1 || die "required command not found: $1"; }

# --- platform detection ----------------------------------------------------
detect_platform() {
  local os arch
  os=$(uname -s)
  arch=$(uname -m)
  case "$os" in
    Linux) ;;
    Darwin) die "macOS desktop/CLI binaries are not published yet. See https://hive.vazac.dev" ;;
    *) die "unsupported OS '$os'. This installer targets Linux servers." ;;
  esac
  case "$arch" in
    x86_64|amd64) echo "linux-x64" ;;
    aarch64|arm64) echo "linux-arm64" ;;
    *) die "unsupported architecture '$arch'. Supported: x86_64, aarch64." ;;
  esac
}

# --- manifest parsing (no jq dependency) -----------------------------------
# The manifest is pretty-printed JSON with a stable field order per artifact:
# kind, platform, filename, sha256, size, url, build_date. We read the
# top-level version, build the deterministic CLI filename, and pull that
# artifact's sha256 by scanning forward from its filename line.
manifest_version() {
  grep -m1 '"version"' "$1" | sed -E 's/.*"version"[[:space:]]*:[[:space:]]*"([^"]+)".*/\1/'
}
sha_for_filename() {
  awk -v f="$2" '
    index($0, "\"filename\": \"" f "\"") { found=1 }
    found && /"sha256"/ {
      line=$0
      sub(/.*"sha256"[[:space:]]*:[[:space:]]*"/, "", line)
      sub(/".*/, "", line)
      print line
      exit
    }
  ' "$1"
}

main() {
  need uname; need curl; need awk; need grep; need sed; need sha256sum; need install; need mktemp

  step "Detecting platform"
  local platform; platform=$(detect_platform)
  ok "platform: ${BOLD}${platform}${RST}"

  # Not `local`: the EXIT trap fires after main() returns, so the temp dir path
  # must live at script scope for cleanup to see it.
  tmp=$(mktemp -d)
  trap 'rm -rf "${tmp:-}"' EXIT

  step "Fetching manifest from ${MANIFEST_URL}"
  curl -fsSL "$MANIFEST_URL" -o "$tmp/manifest.json" \
    || die "could not download manifest from $MANIFEST_URL"

  local version; version=$(manifest_version "$tmp/manifest.json")
  [ -n "$version" ] || die "could not read version from manifest"
  local filename="hive-${version}-${platform}"
  local url="${BASE_URL}/${filename}"
  local want_sha; want_sha=$(sha_for_filename "$tmp/manifest.json" "$filename")
  [ -n "$want_sha" ] || die "manifest has no CLI artifact for ${platform} (looked for ${filename})"
  ok "latest version: ${BOLD}v${version}${RST}"

  step "Downloading ${filename}"
  curl -fSL --progress-bar "$url" -o "$tmp/hive" \
    || die "download failed: $url"

  step "Verifying SHA-256"
  local got_sha; got_sha=$(sha256sum "$tmp/hive" | awk '{print $1}')
  if [ "$got_sha" != "$want_sha" ]; then
    die "checksum mismatch for ${filename}
       expected: ${want_sha}
       got:      ${got_sha}
     Refusing to install a binary that does not match the manifest."
  fi
  ok "checksum verified"
  chmod +x "$tmp/hive"

  # --- privileged install ---------------------------------------------------
  local dest="${INSTALL_DIR}/hive"
  step "Installing to ${dest}"
  if [ -w "$INSTALL_DIR" ]; then
    install -m 0755 "$tmp/hive" "$dest"
  elif [ "$(id -u)" -eq 0 ]; then
    install -m 0755 "$tmp/hive" "$dest"
  else
    warn "${INSTALL_DIR} is not writable by $(id -un); using sudo for this step."
    warn "You will be prompted for your password. Inspect this script first:"
    warn "  ${DIM}${BASE_URL}/install.sh${RST}"
    command -v sudo >/dev/null 2>&1 \
      || die "sudo not found and ${INSTALL_DIR} is not writable. Re-run as root or set HIVE_INSTALL_DIR to a writable path."
    sudo install -m 0755 "$tmp/hive" "$dest"
  fi
  ok "installed ${BOLD}hive v${version}${RST} -> ${dest}"

  # --- next steps -----------------------------------------------------------
  say ""
  say "${GRN}${BOLD}Hive CLI installed.${RST}"
  say ""
  say "Next, run the interactive daemon setup wizard:"
  say "    ${BOLD}hive install${RST}"
  say ""
  say "  ${DIM}# installs and configures the hived daemon (it may ask for sudo)${RST}"
  say ""
  say "Then check it is up and grab your access token:"
  say "    hive daemon status"
  say "    hive daemon get-token"
  say ""
  say "Docs: ${BLU}https://hive.vazac.dev${RST}"
}

main "$@"
