#!/usr/bin/env sh
set -eu

API_URL="${OPEN_BRAIN_API_URL:-https://open-brain-project-production.up.railway.app}"
API_KEY="${OPEN_BRAIN_API_KEY:-}"
DEVICE_ID="${OPEN_BRAIN_DEVICE_ID:-}"
NO_AUTOSTART="${OPEN_BRAIN_NO_AUTOSTART:-false}"
AUTOSTART_METHOD="disabled"
CONSENT_VERSION="2026-05-01"
PACKAGE_VERSION="2026.05.01.8"

# Validate that an API key looks legit before persisting it. v0.5 only
# checked emptiness, which let stray control bytes through. v0.6 enforces
# 32+ chars, no whitespace, no non-printable bytes. Returns 0 if ok, prints
# rejection reason to stderr and returns non-zero otherwise.
validate_api_key() {
  key="$1"
  if [ -z "$key" ]; then
    echo "API key is empty." >&2
    return 1
  fi
  len="${#key}"
  if [ "$len" -lt 32 ]; then
    echo "API key must be at least 32 characters (got $len)." >&2
    return 1
  fi
  # Detect any character outside printable ASCII (0x20..0x7e) including
  # tabs, newlines, control chars, DEL.
  if printf "%s" "$key" | LC_ALL=C grep -qE '[^[:print:]]'; then
    echo "API key contains a non-printable character." >&2
    return 1
  fi
  return 0
}

prompt_value() {
  prompt="$1"
  default="${2:-}"
  secret="${3:-false}"
  if [ ! -r /dev/tty ]; then
    if [ -n "$default" ]; then
      printf "%s" "$default"
      return 0
    fi
    echo "This installer needs an interactive terminal for setup prompts." >&2
    echo "Set OPEN_BRAIN_API_KEY and OPEN_BRAIN_DEVICE_ID, then rerun the installer." >&2
    exit 1
  fi
  if [ -n "$default" ]; then
    printf "%s [%s]: " "$prompt" "$default" > /dev/tty
  else
    printf "%s: " "$prompt" > /dev/tty
  fi
  if [ "$secret" = "true" ]; then
    stty -echo < /dev/tty 2>/dev/null || true
  fi
  IFS= read -r value < /dev/tty || value=""
  if [ "$secret" = "true" ]; then
    stty echo < /dev/tty 2>/dev/null || true
    printf "\n" > /dev/tty
  fi
  if [ -n "$value" ]; then
    printf "%s" "$value"
  else
    printf "%s" "$default"
  fi
}

normalize_bool() {
  value="$(printf "%s" "$1" | tr '[:upper:]' '[:lower:]')"
  case "$value" in
    y|yes|true|1|on|enable|enabled) printf "true" ;;
    *) printf "false" ;;
  esac
}

apt_get() {
  sudo apt-get \
    -o Acquire::Retries=2 \
    -o Acquire::http::Timeout=20 \
    -o Acquire::https::Timeout=20 \
    -o DPkg::Lock::Timeout=120 \
    "$@"
}

if [ -z "$API_KEY" ]; then
  # Loop until the user enters a key that passes shape validation, so a
  # stray paste / Ctrl+V on an empty clipboard / one-byte typo doesn't
  # silently install a corrupt key.
  while true; do
    API_KEY="$(prompt_value "Open Brain API key" "" true)"
    if validate_api_key "$API_KEY"; then
      break
    fi
    echo "Try again or Ctrl+C to abort." >&2
  done
else
  # API_KEY came from env — still validate so a CI script passing a
  # placeholder var can't install garbage.
  if ! validate_api_key "$API_KEY"; then
    exit 1
  fi
fi

HOSTNAME_VALUE="$(hostname 2>/dev/null || echo device)"
UNAME_VALUE="$(uname -s 2>/dev/null | tr '[:upper:]' '[:lower:]' || echo unknown)"
PLATFORM="$UNAME_VALUE"
if [ -n "${ANDROID_ROOT:-}" ] || printf "%s" "${PREFIX:-}" | grep -qi termux; then
  PLATFORM="android"
fi

if command -v pkg >/dev/null 2>&1; then
  pkg install -y curl jq cronie termux-api >/dev/null || pkg install -y curl jq cronie >/dev/null
elif command -v apt-get >/dev/null 2>&1; then
  if ! command -v jq >/dev/null 2>&1 || ! command -v sqlite3 >/dev/null 2>&1 || ! command -v crontab >/dev/null 2>&1; then
    if ! apt_get update; then
      echo "apt-get update could not reach package mirrors quickly enough." >&2
      echo "Check your network or apt mirror, then rerun this installer." >&2
      echo "You can also preinstall dependencies with: sudo apt-get install -y curl jq sqlite3 cron" >&2
      exit 1
    fi
    if ! apt_get install -y curl jq sqlite3 cron; then
      echo "apt-get install failed. Install curl, jq, sqlite3 and cron manually, then rerun this installer." >&2
      exit 1
    fi
  fi
elif [ "$PLATFORM" = "darwin" ]; then
  if ! command -v jq >/dev/null 2>&1 || ! command -v sqlite3 >/dev/null 2>&1; then
    if command -v brew >/dev/null 2>&1; then
      brew install jq sqlite >/dev/null || true
    else
      echo "macOS install requires jq and sqlite3. Install them with Homebrew, then rerun:" >&2
      echo "  brew install jq sqlite" >&2
    fi
  fi
fi

if ! command -v curl >/dev/null 2>&1 || ! command -v jq >/dev/null 2>&1; then
  echo "curl and jq are required. Install them, then rerun this installer." >&2
  exit 1
fi

if [ -z "$DEVICE_ID" ]; then
  DEFAULT_ID="$(printf "%s-%s" "$HOSTNAME_VALUE" "$PLATFORM" | tr '[:upper:]' '[:lower:]' | tr -c 'a-z0-9._:-' '-')"
  DEVICE_ID="$(prompt_value "Device id" "$DEFAULT_ID")"
fi

if [ "$PLATFORM" = "android" ]; then
  INSTALL_DIR="$HOME/bin"
else
  INSTALL_DIR="$HOME/.local/bin"
fi
mkdir -p "$INSTALL_DIR"

CAPTURE_BIN="$INSTALL_DIR/open-brain-capture"
curl -sSL "${API_URL%/}/device-capture.sh" -o "$CAPTURE_BIN"
chmod +x "$CAPTURE_BIN"

AGENT_BIN="$INSTALL_DIR/open-brain-device-agent"
curl -sSL "${API_URL%/}/device-agent.sh" -o "$AGENT_BIN"
chmod +x "$AGENT_BIN"

ACCESS_BIN="$INSTALL_DIR/open-brain-access"

if [ "$PLATFORM" = "android" ]; then
  DEFAULT_BROWSER_HISTORY="false"
else
  DEFAULT_BROWSER_HISTORY="true"
fi
ENABLE_BROWSER_HISTORY="$(prompt_value "Enable automated browser-history summaries?" "$DEFAULT_BROWSER_HISTORY")"
ENABLE_BROWSER_HISTORY="$(normalize_bool "$ENABLE_BROWSER_HISTORY")"

ENABLE_SHELL_HISTORY="$(prompt_value "Enable redacted shell command history summaries?" "false")"
ENABLE_SHELL_HISTORY="$(normalize_bool "$ENABLE_SHELL_HISTORY")"

ENHANCED_CAPTURE="$(prompt_value "Enable enhanced consent-based automatic summaries? (downloads/bookmarks/document metadata/running apps/activity/projects; no keystrokes, screenshots, clipboard, cookies, passwords or raw browser DBs)" "false")"
ENHANCED_CAPTURE="$(normalize_bool "$ENHANCED_CAPTURE")"
CAPTURE_MODE="standard"
if [ "$ENHANCED_CAPTURE" = "true" ]; then
  CAPTURE_MODE="enhanced"
fi

DEFAULT_ENHANCED="false"
if [ "$CAPTURE_MODE" = "enhanced" ]; then
  DEFAULT_ENHANCED="true"
fi
ENABLE_DOWNLOAD_SUMMARY="false"
ENABLE_BOOKMARK_SUMMARY="false"
ENABLE_DOCUMENT_SUMMARY="false"
ENABLE_APP_SUMMARY="false"
ENABLE_ACTIVITY_TIMELINE="false"
ENABLE_GIT_SUMMARY="false"
DOCUMENT_PATHS="$HOME/Documents:$HOME/Desktop"
PROJECT_PATHS="$HOME/code_projects:$HOME/Documents:$HOME/Desktop"

if [ "$PLATFORM" != "android" ]; then
  ENABLE_DOWNLOAD_SUMMARY="$(prompt_value "Enable browser download metadata summaries? (domains and file types only)" "$DEFAULT_ENHANCED")"
  ENABLE_DOWNLOAD_SUMMARY="$(normalize_bool "$ENABLE_DOWNLOAD_SUMMARY")"
  ENABLE_BOOKMARK_SUMMARY="$(prompt_value "Enable bookmark domain summaries? (domains only)" "$DEFAULT_ENHANCED")"
  ENABLE_BOOKMARK_SUMMARY="$(normalize_bool "$ENABLE_BOOKMARK_SUMMARY")"
  ENABLE_DOCUMENT_SUMMARY="$(prompt_value "Enable document filename/metadata summaries from selected folders?" "$DEFAULT_ENHANCED")"
  ENABLE_DOCUMENT_SUMMARY="$(normalize_bool "$ENABLE_DOCUMENT_SUMMARY")"
  if [ "$ENABLE_DOCUMENT_SUMMARY" = "true" ]; then
    DOCUMENT_PATHS="$(prompt_value "Document folders to summarize, separated by ':'" "$DOCUMENT_PATHS")"
  fi
  ENABLE_APP_SUMMARY="$(prompt_value "Enable running app/process name summaries? (names only, no window text or command args)" "$DEFAULT_ENHANCED")"
  ENABLE_APP_SUMMARY="$(normalize_bool "$ENABLE_APP_SUMMARY")"
  ENABLE_ACTIVITY_TIMELINE="$(prompt_value "Enable active app/window activity snapshots? (foreground title + app/process names only, no keystrokes/screenshots/clipboard)" "$DEFAULT_ENHANCED")"
  ENABLE_ACTIVITY_TIMELINE="$(normalize_bool "$ENABLE_ACTIVITY_TIMELINE")"
  ENABLE_GIT_SUMMARY="$(prompt_value "Enable Git/project activity summaries? (repo, branch, dirty count and last commit subject only, no diffs/file contents)" "$DEFAULT_ENHANCED")"
  ENABLE_GIT_SUMMARY="$(normalize_bool "$ENABLE_GIT_SUMMARY")"
  if [ "$ENABLE_GIT_SUMMARY" = "true" ]; then
    PROJECT_PATHS="$(prompt_value "Project folders to summarize, separated by ':'" "$PROJECT_PATHS")"
  fi
fi

ENABLE_ANDROID_NOTIFICATIONS="false"
if [ "$PLATFORM" = "android" ]; then
  ENABLE_ANDROID_NOTIFICATIONS="$(prompt_value "Enable Android notification metadata summaries through Termux:API?" "false")"
  ENABLE_ANDROID_NOTIFICATIONS="$(normalize_bool "$ENABLE_ANDROID_NOTIFICATIONS")"
fi

CONFIG_DIR="$HOME/.config/openbrain"
CONFIG_FILE="$CONFIG_DIR/device.env"
mkdir -p "$CONFIG_DIR"
cat > "$CONFIG_FILE" <<EOF
export OPEN_BRAIN_API_URL="${API_URL%/}"
export OPEN_BRAIN_API_KEY="$API_KEY"
export OPEN_BRAIN_DEVICE_ID="$DEVICE_ID"
export OPEN_BRAIN_ENABLE_BROWSER_HISTORY="$ENABLE_BROWSER_HISTORY"
export OPEN_BRAIN_ENABLE_SHELL_HISTORY="$ENABLE_SHELL_HISTORY"
export OPEN_BRAIN_ANDROID_NOTIFICATIONS="$ENABLE_ANDROID_NOTIFICATIONS"
export OPEN_BRAIN_CAPTURE_MODE="$CAPTURE_MODE"
export OPEN_BRAIN_CONSENT_VERSION="$CONSENT_VERSION"
export OPEN_BRAIN_CAPTURE_CONSENT="accepted"
export OPEN_BRAIN_ENABLE_DOWNLOAD_SUMMARY="$ENABLE_DOWNLOAD_SUMMARY"
export OPEN_BRAIN_ENABLE_BOOKMARK_SUMMARY="$ENABLE_BOOKMARK_SUMMARY"
export OPEN_BRAIN_ENABLE_DOCUMENT_SUMMARY="$ENABLE_DOCUMENT_SUMMARY"
export OPEN_BRAIN_ENABLE_APP_SUMMARY="$ENABLE_APP_SUMMARY"
export OPEN_BRAIN_ENABLE_ACTIVITY_TIMELINE="$ENABLE_ACTIVITY_TIMELINE"
export OPEN_BRAIN_ENABLE_GIT_SUMMARY="$ENABLE_GIT_SUMMARY"
export OPEN_BRAIN_DOCUMENT_PATHS="$DOCUMENT_PATHS"
export OPEN_BRAIN_PROJECT_PATHS="$PROJECT_PATHS"
export OPEN_BRAIN_AUTOSTART_METHOD="$AUTOSTART_METHOD"
export OPEN_BRAIN_CAPTURE_CADENCE="balanced"
export OPEN_BRAIN_CAPTURE_WINDOW_HOURS="6"
export OPEN_BRAIN_PACKAGE_VERSION="$PACKAGE_VERSION"
EOF
chmod 600 "$CONFIG_FILE"

cat > "$CONFIG_DIR/capture-consent.json" <<EOF
{
  "consent_version": "$CONSENT_VERSION",
  "accepted_at": "$(date -Iseconds 2>/dev/null || date)",
  "device_id": "$DEVICE_ID",
  "platform": "$PLATFORM",
  "capture_mode": "$CAPTURE_MODE",
  "package_version": "$PACKAGE_VERSION",
  "capture_cadence": "balanced",
  "capture_window_hours": 6,
  "features": {
    "browser_history_summary": "$ENABLE_BROWSER_HISTORY",
    "shell_history_summary": "$ENABLE_SHELL_HISTORY",
    "download_metadata_summary": "$ENABLE_DOWNLOAD_SUMMARY",
    "bookmark_domain_summary": "$ENABLE_BOOKMARK_SUMMARY",
    "document_metadata_summary": "$ENABLE_DOCUMENT_SUMMARY",
    "running_app_summary": "$ENABLE_APP_SUMMARY",
    "activity_timeline_summary": "$ENABLE_ACTIVITY_TIMELINE",
    "git_project_summary": "$ENABLE_GIT_SUMMARY",
    "android_notification_summary": "$ENABLE_ANDROID_NOTIFICATIONS"
  },
  "boundaries": [
    "no keystrokes",
    "no hidden screenshots or screen recording",
    "no clipboard capture",
    "no browser cookies, passwords or raw browser database upload",
    "no Git diffs, remotes or file contents",
    "no private app scraping",
    "automated captures are staged in Capture Inbox first"
  ]
}
EOF
chmod 600 "$CONFIG_DIR/capture-consent.json"

cat > "$ACCESS_BIN" <<EOF
#!/usr/bin/env sh
set -eu

CONFIG_FILE="$CONFIG_FILE"
AGENT_BIN="$AGENT_BIN"

set_value() {
  key="\$1"
  value="\$2"
  tmp="\$CONFIG_FILE.tmp"
  touch "\$CONFIG_FILE"
  grep -v "^export \$key=" "\$CONFIG_FILE" > "\$tmp" 2>/dev/null || true
  printf 'export %s="%s"\n' "\$key" "\$value" >> "\$tmp"
  mv "\$tmp" "\$CONFIG_FILE"
  chmod 600 "\$CONFIG_FILE" 2>/dev/null || true
  echo "Set \$key=\$value"
}

collector_key() {
  case "\${1:-}" in
    browser|browser-history) echo "OPEN_BRAIN_ENABLE_BROWSER_HISTORY" ;;
    shell|shell-history|terminal) echo "OPEN_BRAIN_ENABLE_SHELL_HISTORY" ;;
    downloads|download) echo "OPEN_BRAIN_ENABLE_DOWNLOAD_SUMMARY" ;;
    bookmarks|bookmark) echo "OPEN_BRAIN_ENABLE_BOOKMARK_SUMMARY" ;;
    documents|document|docs) echo "OPEN_BRAIN_ENABLE_DOCUMENT_SUMMARY" ;;
    apps|processes|process) echo "OPEN_BRAIN_ENABLE_APP_SUMMARY" ;;
    activity|app-focus|timeline) echo "OPEN_BRAIN_ENABLE_ACTIVITY_TIMELINE" ;;
    git|git-activity|projects) echo "OPEN_BRAIN_ENABLE_GIT_SUMMARY" ;;
    notifications|android-notifications) echo "OPEN_BRAIN_ANDROID_NOTIFICATIONS" ;;
    *) echo "Unknown collector: \${1:-}. Use browser, shell, downloads, bookmarks, documents, apps, activity, git, notifications." >&2; exit 2 ;;
  esac
}

show_help() {
  cat <<'HELP'
Open Brain access helper

Usage:
  open-brain-access status
  open-brain-access enable browser|shell|downloads|bookmarks|documents|apps|activity|git|notifications
  open-brain-access disable browser|shell|downloads|bookmarks|documents|apps|activity|git|notifications
  open-brain-access mode standard|enhanced
  open-brain-access cadence balanced|compact|bulk
  open-brain-access window HOURS
  open-brain-access paths "/home/me/Documents:/home/me/Desktop"
  open-brain-access project-paths "/home/me/code_projects:/home/me/Documents"
  open-brain-access pause
  open-brain-access resume
  open-brain-access run all|browser-history|downloads|bookmarks|documents|apps|activity|git-activity|shell-history|android-notifications

Notes:
  - Changes apply to future scheduled runs.
  - pause/resume controls systemd user timers when available; for cron, rerun the installer after manual changes.
  - This helper changes summary collectors only. It does not enable keystroke logging, hidden screenshots, cookie/password capture or private app scraping.
HELP
}

case "\${1:-help}" in
  status)
    grep -E '^export OPEN_BRAIN_(PACKAGE_VERSION|CAPTURE_MODE|CAPTURE_CADENCE|CAPTURE_WINDOW_HOURS|ENABLE_|ANDROID_NOTIFICATIONS|DOCUMENT_PATHS|PROJECT_PATHS)' "\$CONFIG_FILE" 2>/dev/null || true
    ;;
  enable)
    key="\$(collector_key "\${2:-}")"
    set_value "\$key" "true"
    case "\$key" in OPEN_BRAIN_ENABLE_BROWSER_HISTORY) ;; *) set_value "OPEN_BRAIN_CAPTURE_MODE" "enhanced" ;; esac
    ;;
  disable)
    key="\$(collector_key "\${2:-}")"
    set_value "\$key" "false"
    ;;
  mode)
    set_value "OPEN_BRAIN_CAPTURE_MODE" "\${2:-standard}"
    ;;
  cadence)
    case "\${2:-}" in balanced|compact|bulk) set_value "OPEN_BRAIN_CAPTURE_CADENCE" "\$2" ;; *) echo "Use balanced, compact or bulk" >&2; exit 2 ;; esac
    ;;
  window)
    case "\${2:-}" in ''|*[!0-9]*) echo "Window must be a number of hours" >&2; exit 2 ;; *) set_value "OPEN_BRAIN_CAPTURE_WINDOW_HOURS" "\$2" ;; esac
    ;;
  paths)
    set_value "OPEN_BRAIN_DOCUMENT_PATHS" "\${2:-}"
    ;;
  project-paths)
    set_value "OPEN_BRAIN_PROJECT_PATHS" "\${2:-}"
    ;;
  pause)
    systemctl --user stop openbrain-device-capture.timer openbrain-device-heartbeat.timer >/dev/null 2>&1 || true
    echo "Paused systemd timers where available. If this device uses cron, edit crontab -l entries tagged openbrain-device-agent."
    ;;
  resume)
    systemctl --user start openbrain-device-heartbeat.timer openbrain-device-capture.timer >/dev/null 2>&1 || true
    echo "Resumed systemd timers where available. If this device uses cron, rerun the installer to recreate cron entries."
    ;;
  run)
    . "\$CONFIG_FILE"
    "\$AGENT_BIN" "\${2:-all}"
    ;;
  help|-h|--help)
    show_help
    ;;
  *)
    show_help
    exit 2
    ;;
esac
EOF
chmod +x "$ACCESS_BIN"

PROFILE_FILE="$HOME/.profile"
[ -f "$HOME/.bashrc" ] && PROFILE_FILE="$HOME/.bashrc"
[ -f "$HOME/.zshrc" ] && PROFILE_FILE="$HOME/.zshrc"

if ! grep -q "OPEN_BRAIN_API_URL" "$PROFILE_FILE" 2>/dev/null; then
  {
    echo ""
    echo "# Open Brain quick capture"
    echo ". \"$CONFIG_FILE\""
    echo "alias ob=\"$CAPTURE_BIN\""
    echo "alias ob-agent=\"$AGENT_BIN\""
    echo "alias ob-access=\"$ACCESS_BIN\""
  } >> "$PROFILE_FILE"
fi

install_systemd_user() {
  SYSTEMD_DIR="$HOME/.config/systemd/user"
  mkdir -p "$SYSTEMD_DIR"
  cat > "$SYSTEMD_DIR/openbrain-device-heartbeat.service" <<EOF
[Unit]
Description=Open Brain device heartbeat

[Service]
Type=oneshot
EnvironmentFile=$CONFIG_FILE
ExecStart=$AGENT_BIN heartbeat
EOF
  cat > "$SYSTEMD_DIR/openbrain-device-heartbeat.timer" <<EOF
[Unit]
Description=Run Open Brain heartbeat every 5 minutes

[Timer]
OnBootSec=2min
OnUnitActiveSec=5min
Persistent=true

[Install]
WantedBy=timers.target
EOF
  cat > "$SYSTEMD_DIR/openbrain-device-capture.service" <<EOF
[Unit]
Description=Open Brain automated device capture

[Service]
Type=oneshot
EnvironmentFile=$CONFIG_FILE
ExecStart=$AGENT_BIN all
EOF
  cat > "$SYSTEMD_DIR/openbrain-device-capture.timer" <<EOF
[Unit]
Description=Run Open Brain automated capture hourly

[Timer]
OnBootSec=5min
OnUnitActiveSec=1h
Persistent=true

[Install]
WantedBy=timers.target
EOF
  systemctl --user daemon-reload >/dev/null 2>&1 || return 1
  systemctl --user enable --now openbrain-device-heartbeat.timer >/dev/null 2>&1 || return 1
  systemctl --user enable --now openbrain-device-capture.timer >/dev/null 2>&1 || return 1
}

install_cron() {
  (crontab -l 2>/dev/null | grep -v "openbrain-device-agent" ; \
    echo "*/5 * * * * . \"$CONFIG_FILE\" && \"$AGENT_BIN\" heartbeat # openbrain-device-agent" ; \
    echo "7 * * * * . \"$CONFIG_FILE\" && \"$AGENT_BIN\" all # openbrain-device-agent") | crontab -
}

install_macos_launchagent() {
  LAUNCH_DIR="$HOME/Library/LaunchAgents"
  mkdir -p "$LAUNCH_DIR"
  HEARTBEAT_PLIST="$LAUNCH_DIR/uk.openbrain.device-heartbeat.plist"
  CAPTURE_PLIST="$LAUNCH_DIR/uk.openbrain.device-capture.plist"
  cat > "$HEARTBEAT_PLIST" <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key><string>uk.openbrain.device-heartbeat</string>
  <key>ProgramArguments</key>
  <array><string>/bin/sh</string><string>-lc</string><string>. "$CONFIG_FILE" &amp;&amp; "$AGENT_BIN" heartbeat</string></array>
  <key>RunAtLoad</key><true/>
  <key>StartInterval</key><integer>300</integer>
  <key>StandardOutPath</key><string>$CONFIG_DIR/heartbeat.log</string>
  <key>StandardErrorPath</key><string>$CONFIG_DIR/heartbeat.err</string>
</dict>
</plist>
EOF
  cat > "$CAPTURE_PLIST" <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key><string>uk.openbrain.device-capture</string>
  <key>ProgramArguments</key>
  <array><string>/bin/sh</string><string>-lc</string><string>. "$CONFIG_FILE" &amp;&amp; "$AGENT_BIN" all</string></array>
  <key>RunAtLoad</key><true/>
  <key>StartInterval</key><integer>3600</integer>
  <key>StandardOutPath</key><string>$CONFIG_DIR/capture.log</string>
  <key>StandardErrorPath</key><string>$CONFIG_DIR/capture.err</string>
</dict>
</plist>
EOF
  launchctl unload "$HEARTBEAT_PLIST" >/dev/null 2>&1 || true
  launchctl unload "$CAPTURE_PLIST" >/dev/null 2>&1 || true
  launchctl load -w "$HEARTBEAT_PLIST" >/dev/null 2>&1 || return 1
  launchctl load -w "$CAPTURE_PLIST" >/dev/null 2>&1 || return 1
  AUTOSTART_METHOD="macOS LaunchAgent"
}

install_linux_autostart() {
  if command -v systemctl >/dev/null 2>&1 && systemctl --user status >/dev/null 2>&1; then
    if install_systemd_user; then
      AUTOSTART_METHOD="systemd user timers"
      return 0
    fi
    echo "User systemd timers could not be enabled, falling back to cron." >&2
  fi
  install_cron
  AUTOSTART_METHOD="cron"
}

install_termux_boot() {
  mkdir -p "$HOME/.termux/boot" 2>/dev/null || true
  cat > "$HOME/.termux/boot/openbrain-start" <<EOF
#!/data/data/com.termux/files/usr/bin/sh
crond 2>/dev/null || true
. "$CONFIG_FILE"
"$AGENT_BIN" heartbeat >/dev/null 2>&1 || true
EOF
  chmod +x "$HOME/.termux/boot/openbrain-start" 2>/dev/null || true
}

if [ "$NO_AUTOSTART" != "true" ]; then
  if [ "$PLATFORM" = "android" ]; then
    crond 2>/dev/null || true
    install_cron
    AUTOSTART_METHOD="cron + Termux:Boot"
    install_termux_boot
  elif [ "$PLATFORM" = "darwin" ]; then
    install_macos_launchagent || {
      install_cron
      AUTOSTART_METHOD="cron"
    }
  else
    install_linux_autostart
  fi
fi

cat >> "$CONFIG_FILE" <<EOF
export OPEN_BRAIN_AUTOSTART_METHOD="$AUTOSTART_METHOD"
EOF

if [ "$PLATFORM" = "android" ]; then
  mkdir -p "$HOME/.shortcuts" 2>/dev/null || true
  cat > "$HOME/.shortcuts/open-brain-capture" <<EOF
#!/data/data/com.termux/files/usr/bin/sh
echo "Type memory text, then press enter:"
read NOTE
OPEN_BRAIN_API_URL="${API_URL%/}" OPEN_BRAIN_API_KEY="$API_KEY" OPEN_BRAIN_DEVICE_ID="$DEVICE_ID" "$CAPTURE_BIN" "\$NOTE"
EOF
  chmod +x "$HOME/.shortcuts/open-brain-capture" 2>/dev/null || true
fi

. "$CONFIG_FILE"
"$CAPTURE_BIN" "Open Brain device capture installed on $DEVICE_ID"
"$AGENT_BIN" heartbeat || true

echo "Open Brain device capture installed."
echo "Package version: $PACKAGE_VERSION"
echo "Command: $CAPTURE_BIN \"memory text\""
echo "Agent: $AGENT_BIN"
echo "Auto-start: $AUTOSTART_METHOD"
echo "Capture mode: $CAPTURE_MODE"
echo "Capture cadence: balanced, distributed through the day"
echo "Capture window: 6 hours per scheduled collector"
echo "Browser history summaries: $ENABLE_BROWSER_HISTORY"
echo "Shell history summaries: $ENABLE_SHELL_HISTORY"
echo "Download metadata summaries: $ENABLE_DOWNLOAD_SUMMARY"
echo "Bookmark domain summaries: $ENABLE_BOOKMARK_SUMMARY"
echo "Document metadata summaries: $ENABLE_DOCUMENT_SUMMARY"
echo "Running app/process summaries: $ENABLE_APP_SUMMARY"
echo "Activity snapshots: $ENABLE_ACTIVITY_TIMELINE"
echo "Git/project summaries: $ENABLE_GIT_SUMMARY"
[ "$PLATFORM" = "android" ] && echo "Android notifications: $ENABLE_ANDROID_NOTIFICATIONS"
echo "Consent manifest: $CONFIG_DIR/capture-consent.json"
echo "Access helper: $ACCESS_BIN"
echo "Useful access commands:"
echo "  ob-access status"
echo "  ob-access enable documents"
echo "  ob-access disable shell"
echo "  ob-access cadence compact"
echo "  ob-access window 12"
echo "  ob-access run activity"
echo "  ob-access run git-activity"
echo "  ob-access run browser-history"
echo "Shortcut after new shell: ob \"memory text\""
