#!/usr/bin/env bash
# ============================================================================
#  CADENCE — Community Installer  ·  by KomputerMechanic
#  The curl one-liner target. Verifies your membership key, then runs the real
#  installer in a temporary folder that is wiped afterwards. The installer is
#  never stored on your machine.
#
#  Usage (served by the licence Worker):
#     curl -fsSL https://cadence.komputermechanic.com | bash
# ============================================================================
set -euo pipefail
WORKER_URL="https://cadence-clear-meadow.komputermechanic.com"
TUTORIAL_SLUG="cadence"

if [ -t 1 ]; then B=$'\e[1m'; DIM=$'\e[2m'; G=$'\e[38;5;71m'; R=$'\e[38;5;167m'; ACC=$'\e[38;5;214m'; Z=$'\e[0m'
else B=; DIM=; G=; R=; ACC=; Z=; fi

printf '\n  %s%sKomputerMechanic  ~  Cadence%s\n' "$B" "$ACC" "$Z"
printf '  %sContent-automation studio · community installer%s\n\n' "$DIM" "$Z"

command -v curl >/dev/null || { printf '  %scurl is required.%s\n' "$R" "$Z"; exit 1; }

TMP="$(mktemp -d)"; trap 'rm -rf "$TMP"' EXIT

# the "error" from the worker's JSON answer, read properly (a message with a quote in it defeated grep)
_server_reason() {
  python3 -c 'import json, sys
try:
    print((json.load(open(sys.argv[1])).get("error") or "").strip())
except Exception:
    pass' "$1" 2>/dev/null && return 0
  { grep -o '"error":"[^"]*"' "$1" 2>/dev/null || true; } | head -1 | cut -d'"' -f4
}
# membership key — verify, with one extra try in case of a typo
LAST_ERR=""
ATTEMPTS=2; [ -n "${CAD_LICENSE:-}" ] && ATTEMPTS=1
VERIFIED=0
for try in $(seq 1 "$ATTEMPTS"); do
  KEY="${CAD_LICENSE:-}"
  if [ -z "$KEY" ]; then
    [ "$try" -gt 1 ] && printf "  %sLet's try that once more.%s\n" "$DIM" "$Z"
    read -r -p "  Enter your membership key: " KEY </dev/tty || true
  fi
  KEY="$(printf '%s' "$KEY" | tr -d '[:space:]')"
  if [ -z "$KEY" ]; then printf '  %sNo key entered.%s\n' "$R" "$Z"; continue; fi
  printf '  %sVerifying membership...%s\n' "$DIM" "$Z"
  CODE="$(curl -sS -X POST "$WORKER_URL" \
          -H 'Content-Type: application/json' \
          -d "{\"license_key\":\"$KEY\",\"tutorial_slug\":\"$TUTORIAL_SLUG\"}" \
          -D "$TMP/head" -o "$TMP/body" -w '%{http_code}' 2>/dev/null || true)"
  CODE="${CODE:0:3}"; [ -n "$CODE" ] || CODE=000      # curl prints 000 itself when nothing answered
  if [ "$CODE" = "200" ]; then VERIFIED=1; break; fi
  # The server says WHY (install limit, renewal date, payment, wrong installer...): show its words as they
  # are. A Kit buyer at his install limit was told "check your key and your connection" twelve times
  # (2026-10-11). Only a reply that never came is a connection problem.
  ERR="$(_server_reason "$TMP/body")"
  LAST_CODE="$CODE"; LAST_ERR="$ERR"
  if [ -z "$ERR" ]; then
    case "$CODE" in
      000|5??) ERR="Could not reach the membership server. Check this machine's internet connection and try again." ;;
      *)       ERR="The membership server refused this key (HTTP $CODE) without saying why. Contact info@komputermechanic.com" ;;
    esac
  fi
  printf '  %s✗  %s%s\n' "$R" "$ERR" "$Z"
  # a typo is worth a second try; an install limit, a payment or an expired key is not
  case "$CODE:$LAST_ERR" in 403:*[Ii]nvalid*|403:) : ;; 403:*) break ;; esac
done
if [ "$VERIFIED" != "1" ]; then
  # Don't contradict the server. When it told us WHY (e.g. the install limit is reached),
  # repeating "check your key" sends a customer whose key is perfectly valid down the
  # wrong path. Echo guidance that matches the actual reason.
  if [ -n "${LAST_ERR:-}" ]; then
    # the server's own words were printed above, as they are; just close the run
    printf '\n  %sNothing was installed. Questions: info@komputermechanic.com%s\n\n' "$DIM" "$Z"
  else
    case "${LAST_CODE:-000}" in
      000|5??) printf '\n  %s%sCould not reach the membership server.%s Check this machine'"'"'s internet connection and try again.\n\n' "$R" "$B" "$Z" ;;
      *)       printf '\n  %s%sYour key was not accepted.%s Contact info@komputermechanic.com\n\n' "$R" "$B" "$Z" ;;
    esac
  fi
  exit 1
fi
printf '  %s✓ Membership verified.%s\n' "$G" "$Z"

# unpack into the temp folder, stamp the key, run, then wipe
tar -xzf "$TMP/body" -C "$TMP" 2>/dev/null || { printf '  %sInstaller package was invalid.%s\n' "$R" "$Z"; exit 1; }
DIR="$TMP/cadence-installer"
[ -f "$DIR/install.sh" ] || { printf '  %sInstaller not found in package.%s\n' "$R" "$Z"; exit 1; }
CUSTOMER="$(grep -i '^x-km-customer:' "$TMP/head" | tr -d '\r' | awk '{print $2}')"
printf 'membership_key=%s\ncustomer=%s\ninstalled=%s\n' \
  "$KEY" "$CUSTOMER" "$(date -u +%FT%TZ 2>/dev/null || echo now)" > "$DIR/.license" 2>/dev/null || true

printf '  %sStarting the installer...%s\n' "$DIM" "$Z"
cd "$DIR"
# The real installer runs its own licence step; it already verified here, so skip the double-check.
export CAD_SKIP_LICENSE=1
set +e

# ---- Hermes inside a Docker container on this server (the official image and the like) -------
# Same as the NEXORA installer: every RUNNING container is asked whether it holds a Hermes (a
# hermes binary, HERMES_HOME, or a Hermes config), never judged by its name. With more than one
# choice the buyer picks from a numbered list; the installer never picks a container for them.
# With Hermes both on this machine and in containers, both are offered. Unattended runs keep the
# machine itself, exactly as before; CAD_CONTAINER_NAME=<name> picks a container without asking.
_cad_hermes_on_host() { command -v hermes >/dev/null 2>&1 || [ -x "$HOME/.local/bin/hermes" ] || [ -x /usr/local/bin/hermes ]; }
_cad_ctr_is_hermes() {
  timeout 10 docker exec "$1" sh -c 'command -v hermes >/dev/null 2>&1 || [ -n "${HERMES_HOME:-}" ] \
    || ls /opt/data/config.yaml /home/*/.hermes/config.yaml /root/.hermes/config.yaml >/dev/null 2>&1' >/dev/null 2>&1
}
_cad_ctr_has_cadence() {
  timeout 10 docker exec "$1" sh -c '[ -f "${HERMES_HOME:-/opt/data}/cadence-dashboard/server.py" ] || ls /home/*/cadence-dashboard/server.py >/dev/null 2>&1' >/dev/null 2>&1
}
CTR=""; _CTR_OK=""
_HOST_HERMES=""; _cad_hermes_on_host && _HOST_HERMES=1
if [ "$(uname -s 2>/dev/null)" = "Linux" ] && command -v docker >/dev/null 2>&1; then
  _NAMES=(); _IMAGES=(); _FLAGS=()
  while IFS=$'\t' read -r _n _img; do
    [ -n "$_n" ] || continue
    if _cad_ctr_is_hermes "$_n" || printf '%s %s' "$_n" "$_img" | grep -qi hermes; then
      _NAMES+=("$_n"); _IMAGES+=("$_img")
      if _cad_ctr_has_cadence "$_n"; then _FLAGS+=("Cadence already installed"); else _FLAGS+=(""); fi
    fi
  done < <(docker ps --format '{{.Names}}\t{{.Image}}' 2>/dev/null || true)
  _STOPPED="$(docker ps -a --filter status=exited --filter status=created --format '{{.Names}} {{.Image}}' 2>/dev/null | grep -i hermes || true)"
  _cad_list() {
    local i=0
    while [ "$i" -lt "${#_NAMES[@]}" ]; do
      printf '     %s%d)%s %-28s %s%s%s\n' "$B" $((i+1)) "$Z" "${_NAMES[$i]}" "$DIM" "${_IMAGES[$i]}" "$Z"
      [ -n "${_FLAGS[$i]}" ] && printf '        %s%s%s\n' "$ACC" "${_FLAGS[$i]}" "$Z"
      i=$((i+1))
    done
    [ -n "$_STOPPED" ] && { printf '     %snot running (docker start <name> first):%s\n' "$DIM" "$Z"; printf '%s\n' "$_STOPPED" | sed 's/^/        /'; }
    return 0
  }
  if [ -n "${CAD_CONTAINER_NAME:-}" ]; then
    if docker ps --format '{{.Names}}' 2>/dev/null | grep -qx "$CAD_CONTAINER_NAME"; then
      CTR="$CAD_CONTAINER_NAME"; _CTR_OK=1
      printf '\n  %sHermes in Docker: CAD_CONTAINER_NAME picked %s%s\n' "$B" "$CTR" "$Z"
    elif docker ps -a --format '{{.Names}}' 2>/dev/null | grep -qx "$CAD_CONTAINER_NAME"; then
      printf '\n  %sContainer %s exists but is not running.%s Start it, then re-run:\n     docker start %s\n\n' "$R" "$CAD_CONTAINER_NAME" "$Z" "$CAD_CONTAINER_NAME"; exit 1
    else
      printf '\n  %sNo container called %s on this machine%s (CAD_CONTAINER_NAME). Running containers:\n' "$R" "$CAD_CONTAINER_NAME" "$Z"
      docker ps --format '     {{.Names}}  {{.Image}}' 2>/dev/null; echo; exit 1
    fi
  elif [ "${#_NAMES[@]}" -gt 0 ] && [ -n "$_HOST_HERMES" ]; then
    printf '\n  %sHermes is installed on this machine AND running in Docker.%s Where should Cadence go?\n' "$B" "$Z"
    printf '     %s0)%s this machine %s(the Hermes already installed here)%s\n' "$B" "$Z" "$DIM" "$Z"
    _cad_list
    printf '     %sInstalling into a container leaves whatever is on this machine untouched.%s\n' "$DIM" "$Z"
    if ! { : </dev/tty; } 2>/dev/null; then
      printf '\n  %sNo terminal to ask, so Cadence goes on this machine%s (as it always has).\n' "$ACC" "$Z"
      printf '  To install into a container instead, re-run with:  CAD_CONTAINER_NAME=<name>\n\n'
    else
      _try=0; _done=""
      while [ -z "$_done" ] && [ "$_try" -lt 3 ]; do
        read -r -p "  Which one? [0-${#_NAMES[@]}]: " _pick </dev/tty || _pick=""
        if [ "$_pick" = "0" ]; then _done=1; CTR=""
        elif printf '%s' "$_pick" | grep -qE '^[0-9]+$' && [ "$_pick" -ge 1 ] && [ "$_pick" -le "${#_NAMES[@]}" ]; then
          CTR="${_NAMES[$((_pick-1))]}"; _done=1
        elif docker ps --format '{{.Names}}' 2>/dev/null | grep -qx "$_pick"; then
          CTR="$_pick"; _done=1
        else
          [ -n "$_pick" ] && printf '  %s"%s" is not one of the choices.%s\n' "$R" "$_pick" "$Z"
          _try=$((_try+1))
        fi
      done
      [ -z "$_done" ] && { printf '\n  Nothing installed: no target chosen. Re-run and pick one.\n\n'; exit 1; }
      [ -n "$CTR" ] && _CTR_OK=1
    fi
  elif [ "${#_NAMES[@]}" -gt 0 ]; then
    printf '\n  %sNo Hermes on this machine itself, but Hermes is running in Docker:%s\n' "$B" "$Z"
    _cad_list
    printf '     %sNot the one you want? Start the Hermes container you mean, or set CAD_CONTAINER_NAME=<name>.%s\n' "$DIM" "$Z"
    if [ "${#_NAMES[@]}" -eq 1 ]; then
      CTR="${_NAMES[0]}"     # the only one: confirmed below, never assumed
    elif ! { : </dev/tty; } 2>/dev/null; then
      printf '\n  %sMore than one Hermes container and no terminal to ask you.%s Name the one you mean and re-run:\n     CAD_CONTAINER_NAME=<name> curl ... | bash\n\n' "$R" "$Z"; exit 1
    else
      _try=0
      while [ -z "$CTR" ] && [ "$_try" -lt 3 ]; do
        read -r -p "  Which container? [1-${#_NAMES[@]}]: " _pick </dev/tty || _pick=""
        if printf '%s' "$_pick" | grep -qE '^[0-9]+$' && [ "$_pick" -ge 1 ] && [ "$_pick" -le "${#_NAMES[@]}" ]; then
          CTR="${_NAMES[$((_pick-1))]}"; break
        elif docker ps --format '{{.Names}}' 2>/dev/null | grep -qx "$_pick"; then
          CTR="$_pick"; break
        fi
        [ -n "$_pick" ] && printf '  %sNo running container "%s" - a number from the list or an exact name.%s\n' "$R" "$_pick" "$Z"
        _try=$((_try+1))
      done
      [ -z "$CTR" ] && { printf '\n  Nothing installed: no container chosen. Re-run and pick one, or set CAD_CONTAINER_NAME=<name>.\n\n'; exit 1; }
    fi
    if [ -z "$_CTR_OK" ] && { : </dev/tty; } 2>/dev/null; then
      read -r -p "  Install Cadence into container '$CTR'? [Y/n]: " _ok </dev/tty || _ok=""
      case "$_ok" in [Nn]*)
        printf '\n  Nothing installed. Start or name the container you want (CAD_CONTAINER_NAME=<name>) and re-run.\n\n'; exit 0 ;;
      esac
    fi
  elif [ -n "$_STOPPED" ] && [ -z "$_HOST_HERMES" ]; then
    printf '\n  %sNo Hermes on this machine, and the Hermes container(s) here are not running:%s\n' "$R" "$Z"
    printf '%s\n' "$_STOPPED" | sed 's/^/     /'
    printf '  Start the one you want (docker start <name>), then re-run.\n\n'; exit 1
  fi
fi

if [ -n "$CTR" ]; then
  # the user Hermes runs as inside the container: whoever owns its data folder (uid 10000 on the
  # official image). Root via a plain docker exec would leave files Hermes cannot read.
  _CHH="$(docker exec "$CTR" sh -c 'printf %s "${HERMES_HOME:-/opt/data}"' 2>/dev/null || echo /opt/data)"
  _CUSER="$(docker exec "$CTR" sh -c "stat -c %U '$_CHH'" 2>/dev/null || echo hermes)"
  printf '  %sCopying the installer into %s (as %s, data at %s)...%s\n' "$DIM" "$CTR" "$_CUSER" "$_CHH" "$Z"
  docker cp "$TMP/body" "$CTR:/tmp/cadence-installer.tar.gz" >/dev/null 2>&1 \
    || { printf '  %sCould not copy the installer into the container.%s\n' "$R" "$Z"; exit 1; }
  docker cp "$DIR/.license" "$CTR:/tmp/cadence-installer.license" >/dev/null 2>&1 || true
  docker exec "$CTR" chown "$_CUSER" /tmp/cadence-installer.tar.gz /tmp/cadence-installer.license >/dev/null 2>&1 || true
  _CSCRIPT='rm -rf /tmp/cadence-installer && tar -xzf /tmp/cadence-installer.tar.gz -C /tmp \
      && mv -f /tmp/cadence-installer.license /tmp/cadence-installer/.license 2>/dev/null
    cd /tmp/cadence-installer && CAD_SKIP_LICENSE=1 CAD_CONTAINER=1 bash install.sh; rc=$?
    rm -rf /tmp/cadence-installer /tmp/cadence-installer.tar.gz; exit $rc'
  # the tunnel the buyer is told to open goes through THIS server: name it for the installer,
  # since from inside the container the server's address is unknowable (CAD_VPS_HOST set by hand wins)
  [ -n "${CAD_VPS_HOST:-}" ] || CAD_VPS_HOST="$(id -un)@$( { hostname -I 2>/dev/null || true; } | awk '{print $1}')"
  case "$CAD_VPS_HOST" in *@) CAD_VPS_HOST="" ;; esac
  # every CAD_* setting on the server travels into the container, so a re-run can be steered
  _ENVARGS=(-e "CAD_CONTAINER_NAME=$CTR")
  [ -n "$CAD_VPS_HOST" ] && _ENVARGS+=(-e "CAD_VPS_HOST=$CAD_VPS_HOST")
  while IFS= read -r _kv; do _ENVARGS+=(-e "$_kv"); done < <(env | grep -E '^CAD_[A-Z_]+=' | grep -vE '^CAD_(LICENSE|SKIP_LICENSE|CONTAINER|CONTAINER_NAME|VPS_HOST)=' || true)
  printf '  %sRunning the installer inside %s...%s\n' "$DIM" "$CTR" "$Z"
  if { : </dev/tty; } 2>/dev/null; then
    docker exec -it -u "$_CUSER" "${_ENVARGS[@]}" "$CTR" bash -c "$_CSCRIPT" </dev/tty
  else
    docker exec -i -u "$_CUSER" -e CAD_YES=1 "${_ENVARGS[@]}" "$CTR" bash -c "$_CSCRIPT" </dev/null
  fi
  INSTALL_EXIT=$?
  docker exec "$CTR" rm -f /tmp/cadence-installer.tar.gz /tmp/cadence-installer.license >/dev/null 2>&1 || true
else
# ---- pick the installer for this operating system ---------------------------
# macOS ships bash 3.2 (2007, frozen because bash 4 is GPLv3) and lacks GNU tools like
# `timeout` and `grep -P`, and has launchd instead of systemd. It gets its own installer.
# The Linux install.sh is left exactly as tested.
#
# `uname -s` decides — Darwin on every Mac, Linux on every Linux — but we SHOW the answer
# and let the buyer correct it, so a wrong guess can never silently run the wrong one.
OS_NAME="$(uname -s 2>/dev/null || echo unknown)"
if [ "$OS_NAME" = "Darwin" ] && [ -f ./install-macos.sh ]; then
  PICKED="macos"; PICKED_LABEL="macOS"
else
  PICKED="linux"; PICKED_LABEL="Linux"
fi

# Friendly name only — "Darwin" is macOS's internal kernel name and means nothing to a buyer.
printf '\n  %sDetected system:%s %s%s%s\n' "$DIM" "$Z" "$B" "$PICKED_LABEL" "$Z"

# Only ask when there is a terminal AND a choice to make. Piped/unattended runs keep the
# detected answer. CAD_OS=macos|linux overrides without prompting.
if [ -n "${CAD_OS:-}" ]; then
  case "$CAD_OS" in
    macos|Darwin|mac) PICKED="macos"; PICKED_LABEL="macOS" ;;
    linux|Linux)      PICKED="linux"; PICKED_LABEL="Linux" ;;
  esac
  printf '  %sCAD_OS set — using %s.%s\n' "$DIM" "$PICKED_LABEL" "$Z"
elif [ -t 0 ] || [ -e /dev/tty ]; then
  read -r -p "  Is that correct? [Y/n]: " OS_OK </dev/tty || OS_OK=""
  case "$OS_OK" in
    [Nn]*)
      printf '  Which are you on?  %s1%s) Linux   %s2%s) macOS\n' "$B" "$Z" "$B" "$Z"
      read -r -p "  Enter 1 or 2: " OS_PICK </dev/tty || OS_PICK=""
      case "$OS_PICK" in
        2) PICKED="macos"; PICKED_LABEL="macOS" ;;
        *) PICKED="linux"; PICKED_LABEL="Linux" ;;
      esac
      ;;
  esac
fi

if [ "$PICKED" = "macos" ] && [ -f ./install-macos.sh ]; then
  INSTALLER="./install-macos.sh"
else
  [ "$PICKED" = "macos" ] && printf '  %sNo macOS installer in this package — falling back to the standard one.%s\n' "$R" "$Z"
  INSTALLER="./install.sh"
fi
printf '  %sRunning the %s installer...%s\n' "$DIM" "$PICKED_LABEL" "$Z"

bash "$INSTALLER"
INSTALL_EXIT=$?
fi
set -e

if [ "$INSTALL_EXIT" = "0" ]; then
  printf '\n  %sRecording activation...%s\n' "$DIM" "$Z"
  ACT_CODE="$(curl -sS -X POST "$WORKER_URL" \
    -H 'Content-Type: application/json' \
    -d "{\"license_key\":\"$KEY\",\"tutorial_slug\":\"$TUTORIAL_SLUG\",\"action\":\"activate\"}" \
    -o "$TMP/act" -w '%{http_code}' 2>/dev/null || echo 000)"
  if [ "$ACT_CODE" = "200" ]; then
    USED="$(grep -o '"used":[0-9]*' "$TMP/act" 2>/dev/null | cut -d: -f2 || true)"
    LIMIT="$(grep -o '"limit":[0-9]*' "$TMP/act" 2>/dev/null | cut -d: -f2 || true)"
    printf '  %s✓ Activation recorded (%s/%s installs used).%s\n' "$G" "${USED:-?}" "${LIMIT:-?}" "$Z"
  else
    printf '  %s⚠ Could not record activation — the install succeeded, but the count may not have updated.%s\n' "$R" "$Z"
  fi
else
  printf '\n  %s✗ Installation failed — no activation was recorded. Your install count was not affected.%s\n' "$R" "$Z"
  exit "$INSTALL_EXIT"
fi
