#!/usr/bin/env bash
#
# update.sh — Update the Zopu runtime to a specific branch or commit.
#
# Usage:
#   update.sh                    # update to latest dogfood/v0
#   update.sh dogfood/v0         # update to latest of branch dogfood/v0
#   update.sh <commit-sha>       # checkout and build a specific commit
#
# The argument is treated as a branch name first; if no matching remote
# tracking branch exists it is treated as a commit SHA.
#
# .env is gitignored and is never touched by git operations. It survives
# updates and rollbacks unchanged.
#
# Must be run as root (uses runuser to build as the service user).

set -euo pipefail

INSTALL_DIR="${ZOPU_INSTALL_DIR:-/opt/zopu}"
SERVICE_USER="${ZOPU_SERVICE_USER:-zopu}"
TARGET="${1:-dogfood/v0}"

GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'

log()  { echo -e "${GREEN}[update]${NC} $*"; }
warn() { echo -e "${YELLOW}[update]${NC} $*"; }
err()  { echo -e "${RED}[update]${NC} $*" >&2; }

run_as_service() {
  runuser -u "$SERVICE_USER" -- "$@"
}

cd "$INSTALL_DIR"

# Record current commit for rollback
CURRENT_SHA=$(git rev-parse HEAD)
log "Current HEAD: ${CURRENT_SHA:0:12}"
echo "$CURRENT_SHA" > "${INSTALL_DIR}/.last-deployed-sha"

# Fetch all remotes
log "Fetching from origin..."
git fetch origin

# Resolve target: branch first, then commit
if git show-ref --verify --quiet "refs/remotes/origin/${TARGET}"; then
  log "Target is a branch: ${TARGET}"
  git checkout -B "$TARGET" "origin/${TARGET}"
elif git rev-parse --verify "${TARGET}^{commit}" &>/dev/null; then
  log "Target is a commit: ${TARGET:0:12}"
  git checkout "$TARGET"
else
  err "'${TARGET}' is not a known branch or valid commit."
  err "Available branches: $(git branch -r | tr '\n' ' ')"
  exit 1
fi

NEW_SHA=$(git rev-parse HEAD)
log "Now at: ${NEW_SHA:0:12}"

# Restore ownership of the checkout to the service user after git operations
log "Setting ownership of checkout to $SERVICE_USER..."
chown -R "$SERVICE_USER":"$SERVICE_USER" "$INSTALL_DIR"

# Confirm .env is intact and has correct permissions
if [[ -f "${INSTALL_DIR}/.env" ]]; then
  log ".env preserved."
  chmod 600 "${INSTALL_DIR}/.env"
else
  err ".env is missing! Restore it from backup before starting services."
fi

# Install and build
log "Running bun install..."
run_as_service bun install

log "Building web app..."
run_as_service bun run --cwd apps/web build

log "Validating daemon production build..."
run_as_service bun run build:daemon

log "Building agent service..."
run_as_service bun run build:agents

# Graceful restart: daemon first (owns RivetKit engine), then agent and web
log "Restarting services..."
systemctl restart zopu-daemon
sleep 3
systemctl restart zopu-agent
systemctl restart zopu-web
sleep 5

# Health check
HEALTH_SCRIPT="${INSTALL_DIR}/deploy/zopu-runtime/scripts/health-check.sh"
if [[ -x "$HEALTH_SCRIPT" ]]; then
  log "Running health check..."
  if "$HEALTH_SCRIPT"; then
    log "Update complete and healthy."
  else
    err "Health check failed after update!"
    err "  journalctl -u zopu-daemon -n 50"
    err "  journalctl -u zopu-agent -n 50"
    err "  journalctl -u zopu-web -n 50"
    err "To rollback: ${INSTALL_DIR}/deploy/zopu-runtime/scripts/rollback.sh"
    exit 1
  fi
else
  log "Update complete. Verify manually."
fi
