#!/usr/bin/env bash
# ============================================================================
#  AGENT OS — 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). THIS IS THE LIVE ADDRESS - verified, not aspirational:
#     curl -fsSL https://km-agent-os-installer.lingering-frost-ddb0.workers.dev | bash
#
#  Do NOT advertise agentos.komputermechanic.com here. komputermechanic.com's nameservers are
#  Hostinger's, the Cloudflare account has no zone for it, and the same aspirational address sat
#  in another product's bootstrap for months without ever resolving. The workers.dev address answers.
# ============================================================================
set -euo pipefail
WORKER_URL="https://agent-os-brisk-orchard.komputermechanic.com"
TUTORIAL_SLUG="agent-operating-system"

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

printf '\n  %s%sKomputerMechanic  ~  Agent OS%s\n' "$B" "$ACC" "$Z"
printf '  %sOne shared memory for the crew you already have%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 "${AOS_LICENSE:-}" ] && ATTEMPTS=1
VERIFIED=0
for try in $(seq 1 "$ATTEMPTS"); do
  KEY="${AOS_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"
  # --retry alone does not cover a dropped connection; --retry-all-errors does. Validation is
  # read-only server-side, so retrying it never costs an activation.
  CODE="$(curl -sS --retry 3 --retry-delay 2 --retry-all-errors -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/agent-os-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 AOS_SKIP_LICENSE=1
set +e

# ---- Hermes in a Docker container on this VPS (Hostinger's image and the like) ---------------
# On such a box there is no `hermes` on the host at all: it lives inside a container, with its
# data at /opt/data, running as its own user. The installer used to die here at "hermes CLI not
# found". Now: if there is no hermes on the host and a running container looks like Hermes, offer
# to install INTO it - the package is copied in and run as the container's Hermes user, and the
# activation is recorded from the result exactly as for a host install.
#
# WHICH container: the first version only looked at containers whose NAME or IMAGE contained
# "hermes", then quietly took the first of them. A buyer with two Hermes containers - one he
# wanted to keep and a new one for this - got the old one every time, because the new one
# was named after his project, not after Hermes (feedback, 2026-09-10). Now every running
# container is PROBED for Hermes (a hermes binary, HERMES_HOME, or a Hermes config in a home
# dir), the ones that already carry an Agent OS install are flagged, and with more than one the
# BUYER picks from a numbered list - no default, the installer never chooses a container for
# him (it is his setup). Headless with more than one: stop and ask for AOS_CONTAINER_NAME=<name>.
_hermes_on_host() { command -v hermes >/dev/null 2>&1 || [ -x "$HOME/.local/bin/hermes" ] || [ -x /usr/local/bin/hermes ]; }
# does this running container hold a Hermes? asks the container itself, never its name
_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
}
# does this container already carry an Agent OS install?
_ctr_aos_installed() {
  local hh u home
  hh="$(timeout 10 docker exec "$1" sh -c 'printf %s "${HERMES_HOME:-/opt/data}"' 2>/dev/null || true)"
  u="$(timeout 10 docker exec "$1" sh -c "stat -c %U '${hh:-/opt/data}'" 2>/dev/null || true)"
  home="$(timeout 10 docker exec "$1" sh -c "getent passwd '${u:-hermes}' | cut -d: -f6" 2>/dev/null || true)"
  # Agent OS lives in the Hermes home, and its rulebook carries our marker - the
  # same test the installer itself uses to know a wiki is ours.
  timeout 10 docker exec "$1" sh -c \
    "grep -q aos-managed:rulebook '${hh:-/opt/data}/wiki/WIKI.md' 2>/dev/null \
     || { [ -n '$home' ] && grep -q aos-managed:rulebook '$home/wiki/WIKI.md' 2>/dev/null; } \
     || [ -d '${hh:-/opt/data}/agent-os' ]" >/dev/null 2>&1
}
CTR=""
if [ "$(uname -s 2>/dev/null)" = "Linux" ] && ! _hermes_on_host && command -v docker >/dev/null 2>&1; then
  _NAMES=(); _IMAGES=(); _FLAGS=()
  while IFS=$'\t' read -r _n _img; do
    [ -n "$_n" ] || continue
    if _ctr_is_hermes "$_n" || printf '%s %s' "$_n" "$_img" | grep -qi hermes; then
      _NAMES+=("$_n"); _IMAGES+=("$_img")
      if _ctr_aos_installed "$_n"; then _FLAGS+=("Agent OS already installed")
      else _FLAGS+=(""); fi
    fi
  done < <(docker ps --format '{{.Names}}\t{{.Image}}' 2>/dev/null || true)
  # Hermes containers that exist but are NOT running are named too, so "the script does not
  # see my new container" has an answer on screen: start it, then re-run.
  _STOPPED="$(docker ps -a --filter status=exited --filter status=created --format '{{.Names}} {{.Image}}' 2>/dev/null | grep -i hermes || true)"
  if [ -n "${AOS_CONTAINER_NAME:-}" ]; then
    if docker ps --format '{{.Names}}' 2>/dev/null | grep -qx "$AOS_CONTAINER_NAME"; then
      CTR="$AOS_CONTAINER_NAME"; AOS_CONTAINER_OK=1
      printf '\n  %sHermes is running in a Docker container; AOS_CONTAINER_NAME picked %s%s\n' "$B" "$CTR" "$Z"
    elif docker ps -a --format '{{.Names}}' 2>/dev/null | grep -qx "$AOS_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" "$AOS_CONTAINER_NAME" "$Z" "$AOS_CONTAINER_NAME"; exit 1
    else
      printf '\n  %sNo container called %s on this machine%s (AOS_CONTAINER_NAME). Running containers:\n' "$R" "$AOS_CONTAINER_NAME" "$Z"
      docker ps --format '     {{.Names}}  {{.Image}}' 2>/dev/null; echo; exit 1
    fi
  elif [ "${#_NAMES[@]}" -gt 0 ]; then
    printf '\n  %sNo Hermes on this machine itself, but Hermes is running in a Docker container:%s\n' "$B" "$Z"
    _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/^/        /"; }
    printf '     %sNot the one you want? Start the Hermes container you mean, or set AOS_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     AOS_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     # any RUNNING container by name, even one the probe did not flag
        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 AOS_CONTAINER_NAME=<name>.\n\n'; exit 1; }
    fi
    if [ -z "${AOS_CONTAINER_OK:-}" ] && { : </dev/tty; } 2>/dev/null; then
      read -r -p "  Install Agent OS into container '$CTR'? [Y/n]: " _ok </dev/tty || _ok=""
      case "$_ok" in [Nn]*)
        printf '\n  Nothing installed. Start or name the container you want (AOS_CONTAINER_NAME=<name>) and re-run.\n\n'; exit 0 ;;
      esac
    fi
  elif [ -n "$_STOPPED" ]; 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 dir (uid 10000 on the
  # official image). Root via a plain docker exec would leave files the gateway 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/agent-os-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/agent-os-installer.license" >/dev/null 2>&1 || true
  # docker cp keeps OUR uid on the files; in the container's sticky /tmp the Hermes user could
  # then neither move the licence stamp nor remove the package afterwards (found by the lane)
  docker exec "$CTR" chown "$_CUSER" /tmp/agent-os-installer.tar.gz /tmp/agent-os-installer.license >/dev/null 2>&1 || true
  # The installer's prompts read the terminal, so hand it ours (-it, stdin from /dev/tty).
  # Without a terminal (a fully piped run) stdin is /dev/null and AOS_YES answers: NEVER the
  # bootstrap's own stdin, which is this very script arriving from curl - docker exec -i would
  # swallow the rest of it.
  _CSCRIPT='rm -rf /tmp/agent-os-installer && tar -xzf /tmp/agent-os-installer.tar.gz -C /tmp \
      && mv -f /tmp/agent-os-installer.license /tmp/agent-os-installer/.license 2>/dev/null
    cd /tmp/agent-os-installer && AOS_SKIP_LICENSE=1 AOS_CONTAINER=1 bash install.sh; rc=$?
    rm -rf /tmp/agent-os-installer /tmp/agent-os-installer.tar.gz; exit $rc'
  # `-e /dev/tty` is true on every Linux box, even with no terminal attached (the device file
  # exists); only OPENING it tells the truth.
  # every AOS_* knob set on the VPS shell travels into the container (AOS_VPS_HOST, AOS_PORT,
  # AOS_NO_VOICE, AOS_FORCE_REINSTALL, AOS_TG_LINK...), or a re-run could never be steered
  _ENVARGS=()
  while IFS= read -r _kv; do _ENVARGS+=(-e "$_kv"); done < <(env | grep -E '^AOS_[A-Z_]+=' | grep -vE '^AOS_(LICENSE|SKIP_LICENSE|CONTAINER)=' || true)
  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 AOS_YES=1 "${_ENVARGS[@]}" "$CTR" bash -c "$_CSCRIPT" </dev/null
  fi
  INSTALL_EXIT=$?
  docker exec "$CTR" rm -f /tmp/agent-os-installer.tar.gz /tmp/agent-os-installer.license >/dev/null 2>&1 || true
else
# ---- this release is Linux and Hermes-in-Docker ------------------------------
# macOS is not shipped yet, and saying so here - before anything is written - is
# the honest version of "we only sell what we test". The whole install is files
# plus agent turns, so a Mac port is small; it is simply not tested, and an
# untested installer on somebody's working machine is not a product.
OS_NAME="$(uname -s 2>/dev/null || echo unknown)"
if [ "$OS_NAME" = "Darwin" ] && [ -z "${AOS_MACOS_OK:-}" ]; then
  printf '\n  %s%sThis is a Mac.%s\n\n' "$R" "$B" "$Z"
  printf '  Agent OS currently installs on %sLinux%s, including Hermes running in Docker.\n' "$B" "$Z"
  printf '  The macOS build is not released yet. Nothing was changed on this machine\n'
  printf '  and no membership install was used up.\n\n'
  printf '  If your crew runs on a Linux box or a VPS, run this there instead.\n'
  printf '  Questions: %sinfo@komputermechanic.com%s\n\n' "$DIM" "$Z"
  exit 1
fi
INSTALLER="./install.sh"

bash "$INSTALLER"
INSTALL_EXIT=$?
fi   # (host install)
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
