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

# This script needs bash. When it is piped to `sh` (dash on Debian/Ubuntu),
# re-exec under bash: from the local file when there is one, otherwise by
# re-fetching the script, because a piped stdin cannot be rewound.
if [ -z "${BASH_VERSION:-}" ]; then
  if ! command -v bash >/dev/null 2>&1; then
    echo "clusto installer requires bash; install bash and retry" >&2
    exit 1
  fi
  if [ -f "$0" ] && [ -r "$0" ]; then
    exec bash "$0" "$@"
  fi
  script_url="${CLUSTO_SCRIPT_URL:-${HIVE_SCRIPT_URL:-${CLUSTO_BASE_URL:-${HIVE_BASE_URL:-https://dl.clusto.app}}/install.sh}}"
  script_body="$(curl -fsSL "$script_url")" || {
    echo "failed to re-fetch installer from $script_url" >&2
    exit 1
  }
  exec bash -c "$script_body" clusto-install "$@"
fi

set -euo pipefail

# The Clusto distribution host is the default. The legacy host keeps serving
# the same artifacts, so an override still works for anything pinned to it.
BASE_URL="${CLUSTO_BASE_URL:-${HIVE_BASE_URL:-https://dl.clusto.app}}"
MANIFEST_URL="${BASE_URL}/manifest.json"
INSTALL_DIR="${CLUSTO_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://clusto.app" ;;
    *) 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.
# Select by kind + platform and consume the published filename, URL, and hash;
# filenames are not reconstructed because cutovers may rename them.
manifest_version() {
  grep -m1 '"version"' "$1" | sed -E 's/.*"version"[[:space:]]*:[[:space:]]*"([^"]+)".*/\1/'
}
artifact_field() {
  awk -v want_platform="$2" -v want_field="$3" '
    function string_value(line) {
      sub(/^[^:]*:[[:space:]]*"/, "", line)
      sub(/".*/, "", line)
      return line
    }
    /"kind"[[:space:]]*:/ { kind=string_value($0) }
    /"platform"[[:space:]]*:/ { platform=string_value($0) }
    kind == "cli" && platform == want_platform && index($0, "\"" want_field "\"") {
      print string_value($0)
      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; filename=$(artifact_field "$tmp/manifest.json" "$platform" filename)
  local url; url=$(artifact_field "$tmp/manifest.json" "$platform" url)
  local want_sha; want_sha=$(artifact_field "$tmp/manifest.json" "$platform" sha256)
  [ -n "$filename" ] && [ -n "$url" ] && [ -n "$want_sha" ] \
    || die "manifest has no complete CLI artifact for ${platform}"
  ok "latest version: ${BOLD}v${version}${RST}"

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

  step "Verifying SHA-256"
  local got_sha; got_sha=$(sha256sum "$tmp/clusto" | 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/clusto"

  # --- privileged install ---------------------------------------------------
  local dest="${INSTALL_DIR}/clusto"
  step "Installing to ${dest}"
  if [ -w "$INSTALL_DIR" ]; then
    install -m 0755 "$tmp/clusto" "$dest"
  elif [ "$(id -u)" -eq 0 ]; then
    install -m 0755 "$tmp/clusto" "$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 CLUSTO_INSTALL_DIR to a writable path."
    sudo install -m 0755 "$tmp/clusto" "$dest"
  fi
  ok "installed ${BOLD}clusto v${version}${RST} -> ${dest}"

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

if [ "${CLUSTO_INSTALLER_SOURCE_ONLY:-0}" != "1" ]; then
  main "$@"
fi
