#!/usr/bin/env bash
# ============================================================================
# KuttiDB installer.
#
# Downloads the right official binary for your platform from GitHub Releases
# and installs it into your PATH. No build tools required.
#
#   curl -fsSL https://kuttidb.com/install.sh | bash
#
# Installer invocation count: every run of this installer sends one count-only
# HTTPS signal (payload {"schema_version":1} — no installation identifier or
# device details), counted whether the runtime-telemetry answer is Yes or No.
# It is sent once, before the question is asked, and is best-effort: an
# unreachable collector never fails or slows down the install. DO_NOT_TRACK=1
# disables it.
#
# Community telemetry opt-in: the installer asks once whether you want to
# contribute to the community adoption statistics.
#
#   no  (default) -> telemetry-not-included build: the reporter is not
#                    compiled in, so the server can never report.
#   yes           -> telemetry-capable build whose servers report by default
#                    (one delayed, best-effort HTTPS report per day). A shell
#                    env file (~/.config/kuttidb/telemetry.env) is also written
#                    so shells that load it and binaries from older releases
#                    report consistently.
#
# The choice is the opt-in; no further setup is required. Disable anytime with
# `DO_NOT_TRACK=1` or `--telemetry off` (they always win). Details and the
# exact report schema: https://kuttidb.com/telemetry
#
# Options:
#   --version vX.Y.Z   pin a release (default: latest)
#   --bin-dir DIR      install location (default: ~/.local/bin)
#   --telemetry yes|no community-telemetry opt-in (skips the prompt)
#   --help             this message
#
# Environment overrides (useful for mirrors and CI):
#   KUTTIDB_RELEASES_URL  releases base (default
#                         https://github.com/kuttidb/kuttidb/releases)
#   KUTTIDB_VERSION       same as --version
#   KUTTIDB_INSTALL_DIR   same as --bin-dir
#   KUTTIDB_TELEMETRY_OPTIN  same as --telemetry (yes|no)
#   KUTTIDB_OS / KUTTIDB_ARCH  force platform detection
#
# Non-interactive installs (no terminal attached, e.g. CI) default to the
# telemetry-not-included build.
#
# Tarball names: `kuttidb-<version>-<os>-<arch>.tar.gz` is telemetry-free;
# `kuttidb-<version>-telemetry-<os>-<arch>.tar.gz` is telemetry-capable.
# Each tarball contains the `kuttidb` server, `kuttidb-bench`, the embedded
# library (libkuttidb_embed.so / .dylib), and the `kuttidb-cli` client (a
# self-contained binary — no Python needed on your machine).
# Checksums are verified against the release's SHASUMS256.txt before install.
#
# Process doc: docs/operations/RELEASE.md
# ============================================================================
set -euo pipefail

REPO="${KUTTIDB_REPO:-kuttidb/kuttidb}"
BASE="${KUTTIDB_RELEASES_URL:-https://github.com/${REPO}/releases}"
INSTALL_DIR="${KUTTIDB_INSTALL_DIR:-${HOME}/.local/bin}"
WANT_VERSION="${KUTTIDB_VERSION:-}"
TELEMETRY_OPTIN="${KUTTIDB_TELEMETRY_OPTIN:-}"

# ---- output helpers (color only when attached to a terminal) ---------------
if [ -t 1 ] && [ -z "${NO_COLOR:-}" ]; then
  C_GOLD=$'\033[38;5;214m'; C_DIM=$'\033[2m'; C_RED=$'\033[31m'
  C_GREEN=$'\033[32m'; C_OFF=$'\033[0m'
else
  C_GOLD=""; C_DIM=""; C_RED=""; C_GREEN=""; C_OFF=""
fi
info() { printf '%s\n' "${C_GOLD}kuttidb${C_OFF} $*"; }
dim()  { printf '%s\n' "${C_DIM}$*${C_OFF}"; }
fail() { printf '%s\n' "${C_RED}error:${C_OFF} $*" >&2; exit 1; }

# ---- args ------------------------------------------------------------------
while [ $# -gt 0 ]; do
  case "$1" in
    --version)  [ $# -ge 2 ] || fail "--version needs a value (e.g. v0.0.5)"
                WANT_VERSION="$2"; shift 2 ;;
    --bin-dir)  [ $# -ge 2 ] || fail "--bin-dir needs a value"
                INSTALL_DIR="$2"; shift 2 ;;
    --telemetry) [ $# -ge 2 ] || fail "--telemetry needs a value (yes|no)"
                TELEMETRY_OPTIN="$2"; shift 2 ;;
    -h|--help)  sed -n '2,56p' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;;
    *)          fail "unknown argument: $1 (try --help)" ;;
  esac
done

# ---- telemetry opt-in decision ---------------------------------------------
# Accept y/n, true/false, 1/0, on/off (case-insensitive); anything else is an
# error when given explicitly. The interactive prompt defaults to "no".
# Sets NORMALIZED_OPTIN and returns status; prints nothing (safe to call in
# condition contexts).
normalize_optin() {
  case "$(printf '%s' "$1" | tr '[:upper:]' '[:lower:]')" in
    yes|y|true|1|on)  NORMALIZED_OPTIN=yes; return 0 ;;
    no|n|false|0|off) NORMALIZED_OPTIN=no; return 0 ;;
    *) return 1 ;;
  esac
}

if [ -n "$TELEMETRY_OPTIN" ]; then
  normalize_optin "$TELEMETRY_OPTIN" || fail "KUTTIDB_TELEMETRY_OPTIN/--telemetry must be yes or no (got: $TELEMETRY_OPTIN)"
  TELEMETRY_OPTIN="$NORMALIZED_OPTIN"
fi

# ---- installer invocation count (count-only, best-effort) -------------------
# One HTTPS signal per installer run — counted whether the person answers Yes
# or No below. The request carries exactly {"schema_version":1}: no
# installation identifier, no device details, no answer to the question, and
# no local state. Best-effort: unreachable collector, TLS errors, timeouts, or
# rejections are dropped silently and the install continues normally.
INSTALL_COUNT_URL="https://telemetry.kuttidb.com/v1/install"
INSTALL_COUNT_BODY='{"schema_version":1}'
send_installer_count() {
  if [ "${DO_NOT_TRACK:-}" = "1" ]; then
    dim "  installer count: disabled (DO_NOT_TRACK=1). Nothing was sent." >&2
    return 0
  fi
  {
    printf '%s\n' "This installer sends one count-only signal for this run, whether you choose Yes or No below."
    printf '%s\n' "It sends no installation identifier or device details."
    printf '%s\n' "Set DO_NOT_TRACK=1 before running to disable it. Details: https://kuttidb.com/telemetry"
  } >&2
  if command -v curl >/dev/null 2>&1; then
    # -q must be the first option: never honor a user curl config, so no
    # redirects, retries, cookies, or proxies can be injected from it. No -L,
    # no retries, one bounded foreground attempt (at most ~2 seconds); an
    # ambiguous failure is never retried because the server may have counted.
    curl -q -sS -o /dev/null -X POST \
      -A "kuttidb-installer/1" \
      -H "content-type: application/json" \
      --connect-timeout 1 --max-time 2 \
      --data "$INSTALL_COUNT_BODY" \
      "$INSTALL_COUNT_URL" >/dev/null 2>&1 || true
  else
    dim "  installer count: skipped (no suitable HTTP client)." >&2
  fi
}
send_installer_count

if [ -z "$TELEMETRY_OPTIN" ]; then
  if [ -e /dev/tty ] && [ -r /dev/tty ]; then
  # Interactive: ask once. Prompt goes to stderr; the answer is read from the
  # terminal so the classic `curl … | bash` pipe still works.
  {
    printf '%s\n' "${C_GOLD}kuttidb${C_OFF} server telemetry — opt in?"
    printf '%s\n' "KuttiDB can send one anonymous, best-effort HTTPS report per day"
    printf '%s\n' "(after a 15-minute delay) to publish a rounded, community-level"
    printf '%s\n' "picture of adoption: a random installation identifier and one bucket"
    printf '%s\n' "of open connection counts. Never keys, values, queue names, message"
    printf '%s\n' "bodies, paths, hostnames, IPs, or exact client counts."
    printf '%s\n' "Details: https://kuttidb.com/telemetry"
    printf '%s' "Enable optional server telemetry? [y/N] "
  } >&2
  ANSWER=""
  read -r ANSWER </dev/tty || ANSWER=""
  if normalize_optin "${ANSWER:-}"; then
    TELEMETRY_OPTIN="$NORMALIZED_OPTIN"
  else
    TELEMETRY_OPTIN="no"
  fi
  else
  TELEMETRY_OPTIN="no"
  dim "  (no terminal attached: defaulting to the telemetry-not-included build;"
  dim "   opt in with --telemetry yes, or interactively from a real shell)"
  fi
fi

# ---- platform detection ----------------------------------------------------
# KUTTIDB_OS / KUTTIDB_ARCH are canonical wire names (linux|macos, x86_64|arm64)
# and are taken verbatim; otherwise map uname output.
if [ -n "${KUTTIDB_OS:-}" ]; then
  OS="$KUTTIDB_OS"
else
  case "$(uname -s)" in
    Linux)  OS="linux" ;;
    Darwin) OS="macos" ;;
    *) fail "unsupported operating system: $(uname -s)
KuttiDB ships Linux and macOS binaries today; on Windows use WSL2:
  wsl --install" ;;
  esac
fi
if [ -n "${KUTTIDB_ARCH:-}" ]; then
  ARCH="$KUTTIDB_ARCH"
else
  case "$(uname -m)" in
    x86_64|amd64)  ARCH="x86_64" ;;
    arm64|aarch64) ARCH="arm64" ;;
    *) fail "unsupported architecture: $(uname -m) (supported: x86_64, arm64)" ;;
  esac
fi
case "$OS-$ARCH" in
  linux-x86_64|linux-arm64|macos-x86_64|macos-arm64) ;;
  *) fail "unsupported platform: ${OS}-${ARCH} (supported: linux-x86_64, linux-arm64, macos-x86_64, macos-arm64)" ;;
esac

if [ "$TELEMETRY_OPTIN" = yes ]; then
  VARIANT_PART="-telemetry"
  BUILD_LABEL="telemetry-capable build"
else
  VARIANT_PART=""
  BUILD_LABEL="telemetry-not-included build"
fi

# ---- download helper (curl, then wget) -------------------------------------
fetch() { # fetch URL DEST   (DEST "-" = stdout)
  if command -v curl >/dev/null 2>&1; then
    curl -fsSL --retry 3 --retry-delay 1 -o "$2" "$1"
  elif command -v wget >/dev/null 2>&1; then
    wget -q -O "$2" "$1"
  else
    fail "need curl or wget to download (or set KUTTIDB_VERSION and copy the
tarball from https://github.com/${REPO}/releases by hand)"
  fi
}
sha256_of() {
  if command -v sha256sum >/dev/null 2>&1; then sha256sum "$1" | cut -d' ' -f1
  else shasum -a 256 "$1" | cut -d' ' -f1; fi
}

# ---- resolve version and asset name ----------------------------------------
TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT

if [ -n "$WANT_VERSION" ]; then
  VERSION="${WANT_VERSION#v}"
  info "installing KuttiDB ${C_GOLD}v${VERSION}${C_OFF} (${BUILD_LABEL}) for ${OS}-${ARCH}"
  FILENAME="kuttidb-${VERSION}${VARIANT_PART}-${OS}-${ARCH}.tar.gz"
  TARBALL_URL="${BASE}/download/v${VERSION}/${FILENAME}"
  SUMS_URL="${BASE}/download/v${VERSION}/SHASUMS256.txt"
else
  info "resolving the latest release for ${OS}-${ARCH} (${BUILD_LABEL})"
  SUMS_URL="${BASE}/latest/download/SHASUMS256.txt"
  fetch "$SUMS_URL" "$TMP/SHASUMS256.txt"
  # The sums file lists every platform and variant; ours names the version.
  if [ "$TELEMETRY_OPTIN" = yes ]; then
    FILENAME="$(grep -o "kuttidb-[^\` ]*-telemetry-${OS}-${ARCH}\.tar\.gz" "$TMP/SHASUMS256.txt" | head -1 || true)"
  else
    FILENAME="$(grep -o "kuttidb-[^\` ]*-${OS}-${ARCH}\.tar\.gz" "$TMP/SHASUMS256.txt" | grep -v -- '-telemetry-' | head -1 || true)"
  fi
  [ -n "$FILENAME" ] || fail "no ${OS}-${ARCH} ${BUILD_LABEL} found in the latest release
Try pinning one: --version v0.0.5"
  VERSION="${FILENAME#kuttidb-}"; VERSION="${VERSION%-${OS}-${ARCH}.tar.gz}"; VERSION="${VERSION%-telemetry}"
  info "installing KuttiDB ${C_GOLD}v${VERSION}${C_OFF} (${BUILD_LABEL}) for ${OS}-${ARCH}"
  TARBALL_URL="${BASE}/latest/download/${FILENAME}"
fi

# ---- download and verify ----------------------------------------------------
dim "  ↓ ${TARBALL_URL}"
fetch "$TARBALL_URL" "${TMP}/${FILENAME}"
fetch "$SUMS_URL" "$TMP/SHASUMS256.txt"

EXPECTED="$(grep " ${FILENAME}\$" "$TMP/SHASUMS256.txt" | awk '{print $1}' | head -1)"
[ -n "$EXPECTED" ] || fail "checksum for ${FILENAME} missing from SHASUMS256.txt"
ACTUAL="$(sha256_of "${TMP}/${FILENAME}")"
if [ "$ACTUAL" != "$EXPECTED" ]; then
  fail "checksum mismatch for ${FILENAME}
  expected $EXPECTED
  actual   $ACTUAL"
fi
dim "  ✓ sha256 verified"

# ---- unpack and install -----------------------------------------------------
mkdir -p "${TMP}/pkg"
tar -xzf "${TMP}/${FILENAME}" -C "${TMP}/pkg"
PKG_DIR="$(find "${TMP}/pkg" -maxdepth 1 -type d -name 'kuttidb-*' | head -1)"
[ -n "$PKG_DIR" ] || fail "unexpected tarball layout (no kuttidb-* directory)"

mkdir -p "$INSTALL_DIR"
for f in kuttidb kuttidb-cli kuttidb-bench; do
  [ -f "${PKG_DIR}/$f" ] && cp -p "${PKG_DIR}/$f" "${INSTALL_DIR}/$f" && chmod 0755 "${INSTALL_DIR}/$f"
done
for f in "${PKG_DIR}"/libkuttidb_embed.*; do
  [ -e "$f" ] && cp -p "$f" "$INSTALL_DIR/" && chmod 0644 "${INSTALL_DIR}/$(basename "$f")"
done

# ---- apply the telemetry choice ---------------------------------------------
# The opt-in build reports by default (the choice is compiled in). The env
# file additionally covers shells that load it and telemetry-capable binaries
# from older releases; declining removes a previously written env file so the
# choice always sticks.
TELE_ENV_FILE="${XDG_CONFIG_HOME:-${HOME}/.config}/kuttidb/telemetry.env"
if [ "$TELEMETRY_OPTIN" = yes ]; then
  TELE_STATE_DIR="${XDG_STATE_HOME:-${HOME}/.local/state}/kuttidb/telemetry"
  mkdir -p "$TELE_STATE_DIR"
  chmod 0700 "$TELE_STATE_DIR"
  mkdir -p "$(dirname "$TELE_ENV_FILE")"
  {
    printf '# KuttiDB community telemetry — opted in via install.sh on %s\n' "$(date -u '+%Y-%m-%d')"
    printf '# What a server sends once this file is loaded: one delayed (>=15 min),\n'
    printf '# best-effort HTTPS report per day: a random installation identifier and\n'
    printf '# one bucket of open connection counts. Nothing else. Policy and exact\n'
    printf '# schema: https://kuttidb.com/telemetry\n'
    printf '# Turn it off at any time: delete this file, or set DO_NOT_TRACK=1\n'
    printf '# (DO_NOT_TRACK always wins).\n'
    printf 'export KUTTIDB_TELEMETRY=on\n'
    printf 'export KUTTIDB_TELEMETRY_STATE_DIR="%s"\n' "$TELE_STATE_DIR"
  } > "$TELE_ENV_FILE"
  chmod 0644 "$TELE_ENV_FILE"
else
  if [ -e "$TELE_ENV_FILE" ]; then
    rm -f "$TELE_ENV_FILE"
    dim "  removed previous telemetry opt-in: ${TELE_ENV_FILE}"
  fi
fi

# ---- verify the installed build matches the choice --------------------------
FEATURES="$("$INSTALL_DIR/kuttidb" --features 2>/dev/null || true)"
case "$FEATURES" in
  *telemetry=v1*)  INSTALLED_FEATURES="telemetry-capable" ;;
  *telemetry=off*) INSTALLED_FEATURES="telemetry-not-included" ;;
  *)               INSTALLED_FEATURES="unknown" ;;
esac
if [ "$TELEMETRY_OPTIN" = yes ] && [ "$INSTALLED_FEATURES" != "telemetry-capable" ]; then
  dim "  ! expected a telemetry-capable build but 'kuttidb --features' reported: ${INSTALLED_FEATURES}"
elif [ "$TELEMETRY_OPTIN" = no ] && [ "$INSTALLED_FEATURES" != "telemetry-not-included" ]; then
  dim "  ! expected a telemetry-not-included build but 'kuttidb --features' reported: ${INSTALLED_FEATURES}"
fi

# ---- verify the installed CLI runs -------------------------------------------
# kuttidb-cli ships as a self-contained binary (no python3 needed); a smoke
# run catches a corrupted download or an unexpected platform immediately.
if [ -f "$INSTALL_DIR/kuttidb-cli" ] && ! "$INSTALL_DIR/kuttidb-cli" --help >/dev/null 2>&1; then
  dim "  ! kuttidb-cli installed but did not start (report: https://github.com/${REPO}/issues)"
fi

# ---- PATH hint ---------------------------------------------------------------
case ":${PATH}:" in
  *":${INSTALL_DIR}:"*) ;;
  *) dim "  ! ${INSTALL_DIR} is not on your PATH. Add it:"
     dim "      export PATH=\"${INSTALL_DIR}:\$PATH\"   # add to ~/.zshrc or ~/.bashrc" ;;
esac

info "${C_GREEN}installed ✓${C_OFF} kuttidb, kuttidb-cli, kuttidb-bench, libkuttidb_embed → ${INSTALL_DIR}"
dim "  build: ${BUILD_LABEL} (kuttidb --features → telemetry $([ "$TELEMETRY_OPTIN" = yes ] && printf 'v1' || printf 'off'))"
if [ "$TELEMETRY_OPTIN" = yes ]; then
  dim "  telemetry: opted in ✓ servers from this build report by default (first"
  dim "  report ≥15 min after startup, at most once per day). No setup needed."
  dim "  compat env file: ${TELE_ENV_FILE}   # source it to cover older telemetry builds"
  dim "  always off: DO_NOT_TRACK=1 or --telemetry off  ·  change your mind: delete ${TELE_ENV_FILE}"
else
  dim "  runtime telemetry: not included in this build — its server can never report."
  dim "  opt in anytime: re-run the installer with --telemetry yes"
  dim "  (or build from source with: make TELEMETRY=1). https://kuttidb.com/telemetry"
fi
dim "  start a server:  kuttidb 7379 kuttidb.wal"
dim "  full guide:      https://github.com/${REPO}#readme"