#!/usr/bin/env bash
# ═══════════════════════════════════════════════════════════════════════
# hermes-bootstrap.sh — Smart turn-key installer
# https://h.ahamri.nl  →  curl -fsSL https://h.ahamri.nl | bash
# ═══════════════════════════════════════════════════════════════════════
# Detects existing Claude Code / Hermes installs, installs what's missing,
# configures OAuth + fallback AI worker + daily backup to cloud.ahamri.nl.
#
# Flags (with `bash -s -- <flags>` when piping):
#   --reinstall          force reinstall Hermes even if present
#   --no-backup          skip daily backup cron
#   --no-fallback        skip AI worker fallback config
#   --no-test            skip smoke-test prompt
#   --backup-now         run backup immediately after setup
#   --import-auth PATH   import OAuth tokens from a file (skip browser login)
#   --model NAME         override model (default: claude-opus-4-7)
#   --quiet              minimal output
# ═══════════════════════════════════════════════════════════════════════

set -euo pipefail

# ─── Defaults / baked-in config ────────────────────────────────────────
MODEL="claude-opus-4-7"
HERMES_HOME="${HERMES_HOME:-$HOME/.hermes}"
BACKUP_HOME="$HOME/.config/hermes-backup"
FALLBACK_HOME="$HOME/.config/hermes-fallback"

# Nextcloud backup target (private homelab)
NC_URL="https://cloud.ahamri.nl"
NC_USER="admin"
NC_PASS="6b6zDj67Y7EwL4k3xA9r3bmRg8F6EEuksGTrjfOunw9mtUJnITedywagA2qxB0B8hFYt3XUb"
NC_DIR="hermes-backups"

# AI fallback (Cloudflare Access protected)
AI_URL="https://ai.ahamri.nl/v1"
AI_MODEL="qwen3-14b-awq"
AI_CF_CLIENT_ID="40258cc521a50faa587358de6d96eead.access"
AI_CF_CLIENT_SECRET="f1a2f2818deb11cebf46d34a2d8aef36e2b89e1aac68a2e36cc55b6e64c9eda5"

# ─── Flag parsing ──────────────────────────────────────────────────────
REINSTALL=0; DO_BACKUP=1; DO_FALLBACK=1; DO_TEST=1; BACKUP_NOW=0; QUIET=0
IMPORT_AUTH=""
while [[ $# -gt 0 ]]; do
  case "$1" in
    --reinstall)    REINSTALL=1; shift ;;
    --no-backup)    DO_BACKUP=0; shift ;;
    --no-fallback)  DO_FALLBACK=0; shift ;;
    --no-test)      DO_TEST=0; shift ;;
    --backup-now)   BACKUP_NOW=1; shift ;;
    --import-auth)  IMPORT_AUTH="$2"; shift 2 ;;
    --model)        MODEL="$2"; shift 2 ;;
    --quiet)        QUIET=1; shift ;;
    -h|--help)      sed -n '2,22p' "$0"; exit 0 ;;
    *) echo "Unknown flag: $1" >&2; exit 1 ;;
  esac
done

# ─── Pretty output ─────────────────────────────────────────────────────
G=$'\033[0;32m'; Y=$'\033[0;33m'; R=$'\033[0;31m'; C=$'\033[0;36m'; B=$'\033[1m'; X=$'\033[0m'
say()  { [[ $QUIET -eq 1 ]] || printf "%s==>%s %s\n" "$C" "$X" "$*"; }
ok()   { printf "%s ✓%s %s\n" "$G" "$X" "$*"; }
warn() { printf "%s ⚠%s %s\n" "$Y" "$X" "$*"; }
info() { [[ $QUIET -eq 1 ]] || printf "%s  •%s %s\n" "$C" "$X" "$*"; }
die()  { printf "%s ✗%s %s\n" "$R" "$X" "$*" >&2; exit 1; }

# ─── 1. SYSTEM DETECTION ───────────────────────────────────────────────
say "[1/7] Inspecting system"

OS_ID="unknown"; OS_VER="?"
if [[ -r /etc/os-release ]]; then
  . /etc/os-release
  OS_ID="${ID:-unknown}"; OS_VER="${VERSION_ID:-?}"
fi
ARCH=$(uname -m)
HOST=$(hostname)
PY_VER=$(python3 --version 2>&1 | awk '{print $2}' || echo "none")

info "Host: $HOST  ($OS_ID $OS_VER, $ARCH)"
info "Python: $PY_VER"
[[ $EUID -eq 0 ]] || warn "Not running as root — some installs may need sudo"

# Detect package manager
if command -v apt-get >/dev/null; then PM=apt
elif command -v dnf     >/dev/null; then PM=dnf
elif command -v apk     >/dev/null; then PM=apk
else die "No supported package manager (apt/dnf/apk)"
fi
info "Package manager: $PM"

# Detect existing AI CLIs
CLAUDE_CODE_VER=""
HERMES_VER=""
if command -v claude >/dev/null 2>&1; then
  CLAUDE_CODE_VER=$(claude --version 2>&1 | head -1 | tr -d '\n' || true)
  info "Found Claude Code: $CLAUDE_CODE_VER"
fi
if command -v hermes >/dev/null 2>&1; then
  HERMES_VER=$(hermes --version 2>&1 | head -1 | tr -d '\n' || true)
  info "Found Hermes:      $HERMES_VER"
fi

# ─── 2. SYSTEM DEPS ────────────────────────────────────────────────────
say "[2/7] Installing system dependencies"
SUDO=""; [[ $EUID -ne 0 ]] && SUDO="sudo"
NEED=()
for c in python3 git curl jq zip unzip; do
  command -v "$c" >/dev/null || NEED+=("$c")
done
if [[ ${#NEED[@]} -gt 0 ]]; then
  info "Installing: ${NEED[*]}"
  case $PM in
    apt) $SUDO apt-get update -qq
         $SUDO env DEBIAN_FRONTEND=noninteractive apt-get install -y -qq \
              "${NEED[@]}" python3-venv python3-pip cron ca-certificates ;;
    dnf) $SUDO dnf install -y -q "${NEED[@]}" python3-virtualenv python3-pip cronie ca-certificates ;;
    apk) $SUDO apk add --no-cache "${NEED[@]}" py3-virtualenv py3-pip bash dcron ca-certificates ;;
  esac
fi
ok "Deps ready"

# Ensure ~/.local/bin in PATH (persistent + current shell)
mkdir -p "$HOME/.local/bin"
case ":$PATH:" in
  *":$HOME/.local/bin:"*) ;;
  *)
    echo 'export PATH="$HOME/.local/bin:$PATH"' >> "$HOME/.bashrc"
    export PATH="$HOME/.local/bin:$PATH"
    info "Added ~/.local/bin to PATH"
    ;;
esac

# ─── 3. INSTALL / UPDATE HERMES ────────────────────────────────────────
say "[3/7] Hermes Agent"
if [[ -n "$HERMES_VER" && $REINSTALL -eq 0 ]]; then
  ok "Already installed — skipping"
  info "(run with --reinstall to force fresh install)"
else
  info "Downloading official installer"
  if curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash; then
    ok "Hermes installed: $(hermes --version 2>&1 | head -1)"
  else
    die "Hermes installer failed"
  fi
fi

# Post-install (node/ripgrep/ffmpeg) — never fatal
info "Running postinstall (node/ripgrep/ffmpeg)"
hermes postinstall 2>&1 | tail -2 || warn "postinstall had non-fatal warnings"

# ─── 4. CONFIG + AUTH ──────────────────────────────────────────────────
say "[4/7] Configuring Hermes (model: $MODEL)"
mkdir -p "$HERMES_HOME"; chmod 700 "$HERMES_HOME"

# Auth: import or interactive OAuth
if [[ -n "$IMPORT_AUTH" ]]; then
  [[ -f "$IMPORT_AUTH" ]] || die "Auth import file not found: $IMPORT_AUTH"
  jq -e '.credential_pool.anthropic | length > 0' "$IMPORT_AUTH" >/dev/null 2>&1 \
    || die "Invalid auth.json (no credential_pool.anthropic)"
  [[ -f "$HERMES_HOME/auth.json" ]] && cp "$HERMES_HOME/auth.json" "$HERMES_HOME/auth.json.bak.$(date +%Y%m%d_%H%M%S)"
  cp "$IMPORT_AUTH" "$HERMES_HOME/auth.json"
  chmod 600 "$HERMES_HOME/auth.json"
  ok "OAuth tokens imported"
elif hermes auth status anthropic 2>&1 | grep -q "logged in"; then
  ok "Already logged in to Anthropic"
else
  warn "Browser/device-code login coming up. Use your Claude Max x20 account (ahamris@gmail.com)."
  if ! hermes login anthropic; then
    die "OAuth login failed. Run 'hermes login anthropic' manually."
  fi
  ok "OAuth login completed"
fi

# Write model + fallback config (always overwrite our managed block)
say "[5/7] Writing config (model + fallback)"

# Build fallback block conditionally
FALLBACK_BLOCK=""
if [[ $DO_FALLBACK -eq 1 ]]; then
  # Test reachability of AI worker first (don't block install if down)
  info "Testing AI fallback: $AI_URL"
  if curl -fsS --max-time 6 \
       -H "CF-Access-Client-Id: $AI_CF_CLIENT_ID" \
       -H "CF-Access-Client-Secret: $AI_CF_CLIENT_SECRET" \
       "$AI_URL/models" >/dev/null 2>&1; then
    ok "AI fallback reachable — configuring"
    # Stash CF Access creds where Hermes can read them (via env-pass-through)
    mkdir -p "$FALLBACK_HOME"; chmod 700 "$FALLBACK_HOME"
    cat > "$FALLBACK_HOME/env" <<EOF
CF_ACCESS_CLIENT_ID=$AI_CF_CLIENT_ID
CF_ACCESS_CLIENT_SECRET=$AI_CF_CLIENT_SECRET
EOF
    chmod 600 "$FALLBACK_HOME/env"

    FALLBACK_BLOCK=$(cat <<EOF

# ── Auto-managed by hermes-bootstrap ──────────────────────────────────
fallback_model:
  provider: openai
  model: $AI_MODEL
  base_url: $AI_URL
  api_key: cf-access-protected
  extra_headers:
    CF-Access-Client-Id: $AI_CF_CLIENT_ID
    CF-Access-Client-Secret: $AI_CF_CLIENT_SECRET
EOF
)
  else
    warn "AI fallback not reachable from this network — skipping"
    info "(maybe behind firewall; will retry next run)"
  fi
fi

# Write config.yaml atomically with model + (optional) fallback
TMPCFG=$(mktemp)
python3 - "$HERMES_HOME/config.yaml" "$MODEL" "$TMPCFG" <<'PY'
import sys, pathlib, re
src, model, out = sys.argv[1], sys.argv[2], sys.argv[3]
existing = pathlib.Path(src).read_text() if pathlib.Path(src).exists() else ""
# Strip our managed block if present (between sentinels)
existing = re.sub(r'\n# ── Auto-managed by hermes-bootstrap[\s\S]*?(?=\n\w|\Z)', '', existing)
# Ensure model block at top
if re.search(r'(?m)^model:\s*$', existing):
    existing = re.sub(r'(?m)^(  default: ).*$', f'\\1{model}', existing, count=1)
    existing = re.sub(r'(?m)^(  provider: ).*$', '\\1anthropic', existing, count=1)
else:
    existing = f"model:\n  default: {model}\n  provider: anthropic\n  max_tokens: 8192\n" + existing
pathlib.Path(out).write_text(existing.rstrip() + "\n")
PY

# Append fallback block if we have one
if [[ -n "$FALLBACK_BLOCK" ]]; then
  printf "%s\n" "$FALLBACK_BLOCK" >> "$TMPCFG"
fi

mv "$TMPCFG" "$HERMES_HOME/config.yaml"
chmod 600 "$HERMES_HOME/config.yaml"
ok "config.yaml written"

# ─── 6. BACKUP CRON ────────────────────────────────────────────────────
if [[ $DO_BACKUP -eq 1 ]]; then
  say "[6/7] Daily backup → $NC_URL/$NC_DIR/"
  mkdir -p "$BACKUP_HOME"; chmod 700 "$BACKUP_HOME"
  cat > "$BACKUP_HOME/credentials" <<EOF
NC_URL=$NC_URL
NC_USER=$NC_USER
NC_PASS=$NC_PASS
NC_REMOTE_DIR=$NC_DIR
EOF
  chmod 600 "$BACKUP_HOME/credentials"

  cat > "$HOME/.local/bin/hermes-backup" <<'BACKUP_EOF'
#!/usr/bin/env bash
set -euo pipefail
CRED="$HOME/.config/hermes-backup/credentials"
[[ -f "$CRED" ]] || { echo "Missing $CRED"; exit 1; }
# shellcheck disable=SC1090
source "$CRED"
HERMES_HOME="${HERMES_HOME:-$HOME/.hermes}"
HOST=$(hostname -s)
STAMP=$(date +%Y%m%d)
TMP=$(mktemp -d); ZIP="$TMP/${HOST}-${STAMP}.zip"
LOG="$HOME/.config/hermes-backup/last-backup.log"
{
  echo "=== $(date -Iseconds) backup ${HOST}-${STAMP} ==="
  cd "$HERMES_HOME"
  zip -qr "$ZIP" skills/ memories/ config.yaml auth.json .env kanban.db state.db SOUL.md user_profile.json 2>/dev/null || true
  if [[ -d sessions ]]; then
    find sessions -mtime -14 -type f \( -name '*.json' -o -name '*.jsonl' \) -print0 2>/dev/null | xargs -0 zip -qg "$ZIP" 2>/dev/null || true
  fi
  SIZE=$(stat -c %s "$ZIP" 2>/dev/null || stat -f %z "$ZIP")
  echo "Built $(basename "$ZIP") size=$(numfmt --to=iec "$SIZE" 2>/dev/null || echo "$SIZE")"
  HTTP=$(curl -sk -u "$NC_USER:$NC_PASS" -T "$ZIP" \
    "$NC_URL/remote.php/dav/files/$NC_USER/$NC_REMOTE_DIR/$(basename "$ZIP")" \
    -w '%{http_code}' -o /dev/null --max-time 600)
  if [[ "$HTTP" =~ ^(201|204)$ ]]; then
    echo "✓ Uploaded HTTP $HTTP"
  else
    echo "✗ Upload failed HTTP $HTTP"; exit 2
  fi
  rm -rf "$TMP"
  echo "OK $(date -Iseconds)"
} 2>&1 | tee -a "$LOG"
[[ $(stat -c %s "$LOG" 2>/dev/null || echo 0) -gt 1048576 ]] && tail -200 "$LOG" > "$LOG.tmp" && mv "$LOG.tmp" "$LOG"
BACKUP_EOF
  chmod 755 "$HOME/.local/bin/hermes-backup"

  CRON_LINE="17 3 * * * $HOME/.local/bin/hermes-backup >/dev/null 2>&1"
  ( crontab -l 2>/dev/null | grep -v 'hermes-backup' ; echo "$CRON_LINE" ) | crontab -
  ok "Backup script + cron installed (daily 03:17)"

  if command -v systemctl >/dev/null; then
    $SUDO systemctl enable --now cron 2>/dev/null || $SUDO systemctl enable --now cronie 2>/dev/null || true
  fi
else
  warn "[6/7] Backup skipped (--no-backup)"
fi

# ─── 7. VERIFY ─────────────────────────────────────────────────────────
say "[7/7] Verification"

VERSION_OUT=$(hermes --version 2>&1 | head -2)
AUTH_OUT=$(hermes auth status anthropic 2>&1 | tail -3 || echo "?")
echo "$VERSION_OUT" | sed 's/^/   /'
echo "$AUTH_OUT" | sed 's/^/   /'

if [[ $DO_TEST -eq 1 ]]; then
  info "Smoke test prompt"
  if timeout 30 hermes -z "Reply with exactly: OK" 2>&1 | tail -5; then
    :
  else
    warn "Smoke test failed — possibly OAuth quota or network"
  fi
fi

if [[ $BACKUP_NOW -eq 1 && $DO_BACKUP -eq 1 ]]; then
  say "Running first backup"
  "$HOME/.local/bin/hermes-backup"
fi

# ─── DONE ──────────────────────────────────────────────────────────────
echo
ok "Installation complete!"
cat <<EOF

  ${B}Commands:${X}
    hermes                       interactive TUI
    hermes -z "your prompt"      one-shot
    hermes-backup                manual backup
    crontab -l                   show backup cron

  ${B}Files (mode 600):${X}
    $HERMES_HOME/auth.json       OAuth tokens (your account credential)
    $HERMES_HOME/config.yaml     model + fallback config
    $BACKUP_HOME/credentials     Nextcloud upload token
    $FALLBACK_HOME/env           CF Access credentials (if fallback enabled)

  ${B}Re-run anytime${X} (idempotent):
    curl -fsSL https://h.ahamri.nl | bash

  ${B}If primary Claude quota is exhausted${X}, requests auto-fallback to
  ${C}$AI_URL  ($AI_MODEL)${X}

EOF
