#!/usr/bin/env bash
# genie installer — generated for https://pr253.preview.genie.tech
# https://pr253.preview.genie.tech/install
#
# What this does:
#   - Verifies node >= 20 is on your PATH
#   - Verifies this cloud (https://pr253.preview.genie.tech) is reachable
#   - Downloads the genie CLI tarball
#   - Installs to ~/.genie/bin/
#   - Symlinks 'genie' onto your PATH
#   - Writes ~/.genie/config.json so the CLI knows which cloud to talk to
#   - Tells you the next command (genie auth login --device)
#
# Re-running this script is safe — it's idempotent.

set -euo pipefail

CLOUD="https://pr253.preview.genie.tech"
GENIE_HOME="${HOME}/.genie"
BIN_DIR="${GENIE_HOME}/bin"
TARBALL_URL="${CLOUD}/install/cli.tar.gz"
VERSION_URL="${CLOUD}/install/cli.version"
CONFIG_PATH="${GENIE_HOME}/config.json"

c_red()    { printf '\033[31m%s\033[0m' "$1"; }
c_green()  { printf '\033[32m%s\033[0m' "$1"; }
c_yellow() { printf '\033[33m%s\033[0m' "$1"; }
c_dim()    { printf '\033[2m%s\033[0m'  "$1"; }
ok()   { echo "  $(c_green ✓) $*"; }
fail() { echo "  $(c_red ✗) $*"  >&2; exit 1; }
warn() { echo "  $(c_yellow ⚠) $*" >&2; }
step() { echo; echo "$(c_dim '─') $*"; }

step "1/6  Verify node ≥ 20"
if ! command -v node >/dev/null 2>&1; then
  fail "node is not installed.
       macOS:   brew install node
       Linux:   https://nodejs.org/ (use the LTS installer)
       After installing, re-run this script."
fi
NODE_MAJOR="$(node -v | sed 's/^v//' | cut -d. -f1)"
if [ "$NODE_MAJOR" -lt 20 ]; then
  fail "node version $(node -v) is too old. Need ≥ 20.
       macOS:   brew upgrade node
       Or use nvm:   nvm install 20 && nvm use 20"
fi
ok "node $(node -v)"

step "2/6  Verify cloud is reachable"
if ! curl -sf -o /dev/null --max-time 10 "${CLOUD}/.well-known/oauth-authorization-server"; then
  fail "Cannot reach ${CLOUD}.
       If you're behind a Cloudflare tunnel, double-check the tunnel
       is up. If the URL is a LAN address, make sure both machines
       are on the same network."
fi
ok "${CLOUD} responds to /.well-known/oauth-authorization-server"

step "3/6  Verify ~/.genie writable + create dirs"
mkdir -p "${BIN_DIR}" 2>/dev/null \
  || fail "Cannot mkdir ${BIN_DIR}. Is ${HOME} read-only?"
chmod 700 "${GENIE_HOME}"
ok "${GENIE_HOME} ready (mode 700)"

step "4/6  Back up any existing install"
if [ -f "${BIN_DIR}/cli.cjs" ]; then
  ts="$(date +%Y%m%d-%H%M%S)"
  mv "${BIN_DIR}/cli.cjs" "${BIN_DIR}/cli.cjs.bak.${ts}"
  mv "${BIN_DIR}/genie"   "${BIN_DIR}/genie.bak.${ts}" 2>/dev/null || true
  ok "Backed up previous install to *.bak.${ts}"
else
  ok "No previous install"
fi
if [ -f "${HOME}/.genie/credentials.json" ]; then
  warn "Existing credentials found at ~/.genie/credentials.json — KEEPING.
       (Run 'genie auth status' after install to verify; 'genie auth logout' to clear.)"
fi

step "5/6  Download + extract"
NEW_VERSION="$(curl -sf --max-time 10 "${VERSION_URL}" | tr -d '[:space:]' || echo unknown)"
TMP="$(mktemp -d)"
trap "rm -rf ${TMP}" EXIT
curl -fSL --max-time 60 "${TARBALL_URL}" -o "${TMP}/genie-cli.tar.gz" \
  || fail "Failed to download ${TARBALL_URL}"
tar -xzf "${TMP}/genie-cli.tar.gz" -C "${TMP}" \
  || fail "Failed to extract tarball — partial download?"
cp "${TMP}/bin/cli.cjs" "${BIN_DIR}/cli.cjs"
cp "${TMP}/bin/genie"   "${BIN_DIR}/genie"
chmod +x "${BIN_DIR}/genie"
ok "Installed v${NEW_VERSION} to ${BIN_DIR}"

step "6/6  Wire up PATH + config"
# Pick the first writable bin dir on PATH. /usr/local/bin needs sudo
# on most Macs; ~/.local/bin is the modern de-facto user-bin.
LINK_DIR=""
for d in "${HOME}/.local/bin" "${HOME}/bin" "/usr/local/bin"; do
  case ":${PATH}:" in
    *":${d}:"*)
      mkdir -p "$d" 2>/dev/null || continue
      if [ -w "$d" ]; then LINK_DIR="$d"; break; fi
      ;;
  esac
done
if [ -n "${LINK_DIR}" ]; then
  ln -sf "${BIN_DIR}/genie" "${LINK_DIR}/genie"
  ok "Symlinked ${LINK_DIR}/genie → ${BIN_DIR}/genie"
else
  warn "No writable bin dir on PATH. Add this to your shell rc:
       export PATH="${BIN_DIR}:\$PATH""
fi

# Bake api_base into ~/.genie/config.json so 'genie auth login' just works.
cat > "${CONFIG_PATH}" <<EOF
{
  "api_base": "${CLOUD}"
}
EOF
chmod 644 "${CONFIG_PATH}"
ok "Wrote ${CONFIG_PATH}"

# Bake the trusted minisign pubkey alongside api_base so a fresh CLI install
# verifies 'genie update' artifacts out-of-the-box. The pubkey is sourced
# from the cloud env var GENIE_MINISIGN_PUBKEY at render time — rotation is
# a Vercel env change, not a CLI release.
# >>> minisign-pubkey-write
# Decode the base64-encoded pubkey to a tempfile (avoids piping a multi-line
# secret through any shell quoting layer) then call node to merge it into
# config.json under `minisign_pubkey`. Node is guaranteed present — step 1/6
# refused to continue without node >= 20.
GENIE_MINISIGN_PUBKEY_B64='dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXkgN0YxRDZBNjJCNzg5RTBBMQpSV1NoNEltM1ltb2RmMmxKanFKcS9vM3RmOUwvLzd3dE5kRUcwUVFaT05CSGN2T0hKaTNHeDFLNw=='
_pk_tmp="$(mktemp)"
echo "${GENIE_MINISIGN_PUBKEY_B64}" | base64 --decode > "${_pk_tmp}"
GENIE_INSTALL_CFG_PATH="${CONFIG_PATH}" GENIE_INSTALL_PK_PATH="${_pk_tmp}" node -e '
  const { readFileSync, writeFileSync } = require("node:fs");
  const cfgPath = process.env.GENIE_INSTALL_CFG_PATH;
  const pkPath  = process.env.GENIE_INSTALL_PK_PATH;
  let cfg = {};
  try { cfg = JSON.parse(readFileSync(cfgPath, "utf8")); }
  catch (e) {
    if (e && e.code !== "ENOENT") {
      process.stderr.write("note: prior " + cfgPath + " was unreadable (" + e.message + "); recreating\n");
    }
  }
  if (cfg === null || typeof cfg !== "object" || Array.isArray(cfg)) cfg = {};
  cfg.minisign_pubkey = readFileSync(pkPath, "utf8");
  writeFileSync(cfgPath, JSON.stringify(cfg, null, 2) + "\n");
'
rm -f "${_pk_tmp}"
chmod 600 "${CONFIG_PATH}"
ok "Recorded signing pubkey in ${CONFIG_PATH} ('genie update' will verify against it)"
# <<< minisign-pubkey-write

echo
echo "$(c_green ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━)"
echo
echo "  Installed. Next:"
echo
echo "    $(c_green '$') genie auth login --device"
echo
echo "  This will print a short code; visit ${CLOUD}/oauth/device on any"
echo "  signed-in browser, enter the code, and approve. Then:"
echo
echo "    $(c_green '$') genie context save \"hello from $(hostname)\""
echo "    $(c_green '$') genie context ls"
echo
