#!/usr/bin/env bash
# Kaidera OS Commercial - secure website install bootstrap.
#
# This is the ONLY piece you fetch directly. It downloads the latest signed release from
# kaidera.ai, VERIFIES its minisign signature + SHA-256, and only then extracts
# and runs install.sh. A tampered or corrupt artifact fails verification and aborts — so the
# rest of the install is trustworthy even though this tiny script is fetched over the wire.
#
# Trust root: the minisign PUBLIC key embedded below (NOT downloaded). An attacker who swaps
# the release tarball cannot forge a signature for it without the matching PRIVATE key.
#
# Install on a new PC (prereqs: curl + Python 3 + minisign):
#   curl -fsSLO https://kaidera.ai/downloads/kaidera-os/server/install.sh && bash install.sh
set -euo pipefail

BASE_URL="${KAIDERA_OS_COMMERCIAL_BASE_URL:-https://kaidera.ai/downloads/kaidera-os/server}"
TAG="${KAIDERA_RELEASE:-latest}"          # or pin a specific vX.Y.Z
DEFAULT_DEST="$HOME/kaidera-os-commercial"
DEST="${KAIDERA_DEST:-$DEFAULT_DEST}"        # where the app is installed
WORK="$(mktemp -d)"; trap 'rm -rf "$WORK"' EXIT

# The minisign PUBLIC key — the root of trust. Populated by dist/setup-signing.sh.
MINISIGN_PUBKEY="RWT3GqtwZl9yMMzCsenpPRoefIRB67QCXcF3SC3Y4YJ3eE7KEXXmnIs6"

say(){ printf '\n\033[1;36m== %s ==\033[0m\n' "$*"; }
ok(){  printf '  \033[32m✓\033[0m %s\n' "$*"; }
die(){ printf '\033[31m✗ %s\033[0m\n' "$*" >&2; exit 1; }

# --- preflight ---------------------------------------------------------------------------
command -v curl >/dev/null 2>&1     || die "curl is required."
command -v python3 >/dev/null 2>&1  || die "Python 3 is required."
command -v minisign >/dev/null 2>&1 || die "minisign required: 'brew install minisign' (macOS) or your package manager (Linux)."
case "$MINISIGN_PUBKEY" in RWQ__RUN*) die "bootstrap not configured — the publisher must run dist/setup-signing.sh to embed the public key." ;; esac

# --- 1. download the signed release ------------------------------------------------------
say "Downloading signed commercial release ($TAG) from $BASE_URL"
if [ "$TAG" = "latest" ]; then
  curl -fsSL "$BASE_URL/latest-server.json" -o "$WORK/latest-server.json" \
    || die "could not download commercial release metadata."
  ARTIFACT="$(python3 - "$WORK/latest-server.json" <<'PY'
import json
import re
import sys

try:
    value = json.load(open(sys.argv[1], encoding="utf-8"))["artifact"]
except (OSError, KeyError, TypeError, ValueError):
    raise SystemExit(1)
if not isinstance(value, str) or not re.fullmatch(
    r"kaidera-os-commercial-v[0-9]+\.[0-9]+\.[0-9]+\.tar\.gz", value
):
    raise SystemExit(1)
print(value)
PY
  )" || die "commercial release metadata contains an invalid artifact name."
else
  case "$TAG" in v*) ;; *) TAG="v$TAG" ;; esac
  python3 -c 'import re,sys; raise SystemExit(not re.fullmatch(r"v[0-9]+\.[0-9]+\.[0-9]+", sys.argv[1]))' \
    "$TAG" || die "invalid release tag: $TAG"
  ARTIFACT="kaidera-os-commercial-$TAG.tar.gz"
fi
curl -fsSL "$BASE_URL/$ARTIFACT" -o "$WORK/$ARTIFACT" \
  || die "commercial archive download failed."
curl -fsSL "$BASE_URL/$ARTIFACT.sha256" -o "$WORK/$ARTIFACT.sha256" \
  || die "commercial checksum download failed."
curl -fsSL "$BASE_URL/$ARTIFACT.minisig" -o "$WORK/$ARTIFACT.minisig" \
  || die "commercial signature download failed."
TARBALL="$WORK/$ARTIFACT"
ok "got $(basename "$TARBALL")"

# --- 2. verify INTEGRITY (SHA-256) -------------------------------------------------------
say "Verifying integrity (SHA-256)"
( cd "$WORK" && {
    if command -v sha256sum >/dev/null 2>&1; then sha256sum -c "$(basename "$TARBALL").sha256";
    else shasum -a 256 -c "$(basename "$TARBALL").sha256"; fi
  } ) >/dev/null || die "SHA-256 MISMATCH — the download is corrupt or tampered. Aborting."
ok "checksum matches"

# --- 3. verify AUTHENTICITY (minisign signature against the embedded key) -----------------
say "Verifying authenticity (minisign signature)"
minisign -V -P "$MINISIGN_PUBKEY" -m "$TARBALL" >/dev/null \
  || die "SIGNATURE INVALID — this release is NOT authentic (or was tampered). Aborting."
ok "signature valid — authentic release"

# --- 4. extract + install ----------------------------------------------------------------
say "Installing to $DEST"
if [ -d "$DEST/.git" ] && [ "${KAIDERA_ALLOW_GIT_DEST:-0}" != "1" ]; then
  die "refusing to install a redistributable into a Git checkout: $DEST
Set KAIDERA_DEST to a dedicated install directory, or use ./install.sh inside development checkouts.
Override only for one-off recovery with KAIDERA_ALLOW_GIT_DEST=1."
fi
EXTRACT="$WORK/extract"
mkdir -p "$DEST" "$EXTRACT"

tar -xzf "$TARBALL" -C "$EXTRACT"
SRCROOT="$(find "$EXTRACT" -mindepth 1 -maxdepth 1 -type d | head -1)"
[ -n "$SRCROOT" ] && [ -d "$SRCROOT" ] || die "release archive did not contain a top-level directory."
[ -x "$SRCROOT/install.sh" ] || die "signed release is missing an executable install.sh."
bash -n "$SRCROOT/install.sh" || die "signed release install.sh failed syntax validation."
command -v rsync >/dev/null 2>&1 \
  || die "rsync is required for transactional commercial upgrades."

RELEASE_VERSION="$(python3 - "$ARTIFACT" "$SRCROOT/local-cortex/console/app/version.py" <<'PY'
import pathlib
import re
import sys

artifact = re.fullmatch(
    r"kaidera-os-commercial-v([0-9]+\.[0-9]+\.[0-9]+)\.tar\.gz",
    sys.argv[1],
)
source = re.search(
    r'__version__\s*=\s*"([0-9]+\.[0-9]+\.[0-9]+)"',
    pathlib.Path(sys.argv[2]).read_text(encoding="utf-8"),
)
if not artifact or not source or artifact.group(1) != source.group(1):
    raise SystemExit(1)
print(source.group(1))
PY
)" || die "signed release version does not match its artifact name."

INSTALLED_VERSION=""
if [ -f "$DEST/local-cortex/console/app/version.py" ]; then
  INSTALLED_VERSION="$(python3 - "$DEST/local-cortex/console/app/version.py" <<'PY'
import pathlib
import re
import sys

match = re.search(
    r'__version__\s*=\s*"([0-9]+\.[0-9]+\.[0-9]+)"',
    pathlib.Path(sys.argv[1]).read_text(encoding="utf-8"),
)
print(match.group(1) if match else "")
PY
)"
fi
if [ -n "$INSTALLED_VERSION" ] && [ "${KAIDERA_OS_ALLOW_DOWNGRADE:-0}" != "1" ]; then
  python3 - "$RELEASE_VERSION" "$INSTALLED_VERSION" <<'PY' \
    || die "refusing downgrade from $INSTALLED_VERSION to $RELEASE_VERSION; set KAIDERA_OS_ALLOW_DOWNGRADE=1 only for approved recovery."
import sys

requested = tuple(map(int, sys.argv[1].split(".")))
installed = tuple(map(int, sys.argv[2].split(".")))
raise SystemExit(0 if requested >= installed else 1)
PY
fi

RSYNC_EXCLUDES=(
  --exclude='.git/'
  --exclude='.env'
  --exclude='.envrc'
  --exclude='.dogfood-backup/'
  --exclude='.kaidera-os/'
  --exclude='.local/'
  --exclude='.playwright-cli/'
  --exclude='.agents/agents/'
  --exclude='.agents/backups/'
  --exclude='.agents/config/autonomy-policy.json'
  --exclude='.agents/config/beat.env'
  --exclude='.agents/config/runtime.yaml'
  --exclude='.agents/config/sync.yaml'
  --exclude='.agents/config/workspace.json'
  --exclude='beat/logs/'
  --exclude='beat/state/'
  --exclude='local-cortex/.console-host'
  --exclude='local-cortex/.env'
  --exclude='local-cortex/console/.venv/'
  --exclude='local-cortex/logs/'
  --exclude='output/'
)

BACKUP=""
if find "$DEST" -mindepth 1 -maxdepth 1 -print -quit | grep -q .; then
  BACKUP="$WORK/previous-install"
  mkdir -p "$BACKUP"
  rsync -a "${RSYNC_EXCLUDES[@]}" "$DEST"/ "$BACKUP"/ \
    || die "could not create the transactional source backup."
fi

# Synchronize only after the signed source and downgrade boundary are proven.
rsync -a --delete "${RSYNC_EXCLUDES[@]}" "$SRCROOT"/ "$DEST"/

cd "$DEST"
chmod 0700 ./install.sh 2>/dev/null || true
if ./install.sh; then
  ok "commercial runtime v$RELEASE_VERSION installed"
else
  status=$?
  if [ -n "$BACKUP" ]; then
    rsync -a --delete "${RSYNC_EXCLUDES[@]}" "$BACKUP"/ "$DEST"/ || true
    systemctl --user restart kaidera-cortex.service >/dev/null 2>&1 || true
    if command -v sudo >/dev/null 2>&1; then
      sudo systemctl restart kaidera-os-console.service >/dev/null 2>&1 || true
    fi
  fi
  die "installation failed with status $status; the previous signed source was restored."
fi
