#!/bin/sh
# Installs the commits.sh CLI collector for headless Macs and cloud servers.
set -eu

BASE_URL="${COMMITS_SH_URL:-https://commits.sh}"
SHARE_DIR="${HOME}/.local/share/commits-sh"
BIN_DIR="${HOME}/.local/bin"
AGENT="${SHARE_DIR}/commits-sh-agent.mjs"
WRAPPER="${BIN_DIR}/commits-sh-agent"

fail() {
  printf 'commits.sh installer: %s\n' "$*" >&2
  exit 1
}

command -v curl >/dev/null 2>&1 || fail "curl is required"
command -v node >/dev/null 2>&1 || fail "Node.js 20 or newer is required for the CLI option. Use the Mac app for a zero-dependency install."
NODE_MAJOR="$(node -p 'Number(process.versions.node.split(".")[0])')"
[ "$NODE_MAJOR" -ge 20 ] || fail "Node.js 20 or newer is required (found $(node --version))."

case "$BASE_URL" in
  https://*) ;;
  http://localhost:*|http://127.0.0.1:*) ;;
  *) fail "COMMITS_SH_URL must use HTTPS (localhost is allowed for development)." ;;
esac

if [ "$(uname -s)" = "Darwin" ] && [ "${COMMITS_SH_FORCE_CLI:-0}" != "1" ]; then
  if [ -d /Applications/commits.sh.app ] || pgrep -x CommitsSH >/dev/null 2>&1; then
    fail "The commits.sh Mac app is already installed. It already streams in the background; do not run a second collector."
  fi
fi

mkdir -p "$SHARE_DIR" "$BIN_DIR"
TEMP="${AGENT}.$$"
CHECKSUM="${TEMP}.sha256"
trap 'rm -f "$TEMP" "$CHECKSUM"' EXIT HUP INT TERM
if [ "${BASE_URL#https://}" != "$BASE_URL" ]; then
  curl -fsSL --proto '=https' --proto-redir '=https' --tlsv1.2 --retry 3 --connect-timeout 15 \
    "${BASE_URL}/downloads/commits-sh-agent.mjs" -o "$TEMP"
  curl -fsSL --proto '=https' --proto-redir '=https' --tlsv1.2 --retry 3 --connect-timeout 15 \
    "${BASE_URL}/downloads/commits-sh-agent.mjs.sha256" -o "$CHECKSUM"
else
  curl -fsSL --retry 3 --connect-timeout 15 "${BASE_URL}/downloads/commits-sh-agent.mjs" -o "$TEMP"
  curl -fsSL --retry 3 --connect-timeout 15 "${BASE_URL}/downloads/commits-sh-agent.mjs.sha256" -o "$CHECKSUM"
fi

EXPECTED="$(awk 'NR == 1 && length($1) == 64 && $1 !~ /[^a-fA-F0-9]/ { print tolower($1) }' "$CHECKSUM")"
[ -n "$EXPECTED" ] || fail "the published CLI checksum is invalid"
if command -v shasum >/dev/null 2>&1; then
  ACTUAL="$(shasum -a 256 "$TEMP" | awk '{print $1}')"
elif command -v sha256sum >/dev/null 2>&1; then
  ACTUAL="$(sha256sum "$TEMP" | awk '{print $1}')"
else
  fail "shasum or sha256sum is required to verify the CLI agent"
fi
[ "$ACTUAL" = "$EXPECTED" ] || fail "CLI agent checksum verification failed"
chmod 755 "$TEMP"
mv "$TEMP" "$AGENT"

cat > "$WRAPPER" <<EOF
#!/bin/sh
exec "$(command -v node)" "$AGENT" "\$@"
EOF
chmod 755 "$WRAPPER"

"$WRAPPER" pair

BACKGROUND_STATUS="manual"
BACKGROUND_NOTE="No compatible per-user service manager is available."

case "$(uname -s)" in
  Darwin)
    PLIST="${HOME}/Library/LaunchAgents/sh.commits.cli-agent.plist"
    mkdir -p "${HOME}/Library/LaunchAgents" "${HOME}/Library/Logs"
    cat > "$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>sh.commits.cli-agent</string>
  <key>ProgramArguments</key><array>
    <string>$(command -v node)</string><string>$AGENT</string><string>run</string><string>--watch</string>
  </array>
  <key>RunAtLoad</key><true/>
  <key>KeepAlive</key><dict><key>NetworkState</key><true/></dict>
  <key>ProcessType</key><string>Background</string>
  <key>ThrottleInterval</key><integer>10</integer>
  <key>StandardOutPath</key><string>${HOME}/Library/Logs/commits-sh-agent.log</string>
  <key>StandardErrorPath</key><string>${HOME}/Library/Logs/commits-sh-agent.log</string>
</dict></plist>
EOF
    DOMAIN="gui/$(id -u)"
    if launchctl print "$DOMAIN" >/dev/null 2>&1; then
      launchctl bootout "$DOMAIN/sh.commits.cli-agent" >/dev/null 2>&1 || true
      if launchctl bootstrap "$DOMAIN" "$PLIST" \
        && launchctl kickstart -k "$DOMAIN/sh.commits.cli-agent"; then
        BACKGROUND_STATUS="running"
        BACKGROUND_NOTE="The LaunchAgent restarts after crashes and at every graphical login."
      else
        BACKGROUND_NOTE="The LaunchAgent was installed but macOS could not start it in the current login session."
      fi
    else
      BACKGROUND_STATUS="next-login"
      BACKGROUND_NOTE="No graphical launchd domain is active; the installed LaunchAgent will start at the next login."
    fi
    ;;
  Linux)
    if command -v systemctl >/dev/null 2>&1 && systemctl --user show-environment >/dev/null 2>&1; then
      SERVICE_DIR="${HOME}/.config/systemd/user"
      mkdir -p "$SERVICE_DIR"
      cat > "${SERVICE_DIR}/commits-sh-agent.service" <<EOF
[Unit]
Description=commits.sh aggregate AI usage streamer
After=network-online.target

[Service]
ExecStart=$(command -v node) $AGENT run --watch
Restart=always
RestartSec=10

[Install]
WantedBy=default.target
EOF
      if systemctl --user daemon-reload \
        && systemctl --user enable --now commits-sh-agent.service; then
        BACKGROUND_STATUS="running"
        BACKGROUND_NOTE="The systemd user service restarts after failures and at login."
        if command -v loginctl >/dev/null 2>&1 \
          && loginctl enable-linger "$(id -un)" >/dev/null 2>&1 \
          && [ "$(loginctl show-user "$(id -un)" -p Linger --value 2>/dev/null || true)" = "yes" ]; then
          BACKGROUND_NOTE="The systemd user service restarts after failures and boots before login (linger enabled)."
        else
          BACKGROUND_NOTE="The service is running and starts at login. To stream before login, an administrator must enable systemd linger for $(id -un)."
        fi
      else
        BACKGROUND_NOTE="The systemd user manager exists, but it could not enable or start the service."
      fi
    fi
    ;;
esac

case "$BACKGROUND_STATUS" in
  running)
    printf '\ncommits.sh is installed and streaming as a background service.\n'
    ;;
  next-login)
    printf '\ncommits.sh is installed and paired; streaming will start at the next graphical login.\n'
    ;;
  *)
    printf '\ncommits.sh is installed and paired, but no background service was started.\n'
    printf 'Run this under your process manager:\n  %s run --watch\n' "$WRAPPER"
    ;;
esac
printf '%s\n' "$BACKGROUND_NOTE"
printf 'Status: %s status\n' "$WRAPPER"
printf 'Live profile: %s\n' "$BASE_URL"
