#!/usr/bin/env bash
#
# deploy.sh — run this ON THE SERVER, from inside the cloned repo
#             (the app lives at /opt/bizgaze-support).
#
# What it does:
#   1. Snapshots the current working tree (code + .env + certs, excluding .git)
#      into a rotating backup, keeping the newest $KEEP_BACKUPS.
#   2. Pulls the latest commit of $GIT_BRANCH (git reset --hard, so the box
#      always matches origin exactly).
#   3. Rebuilds the image and recreates the container. The named data volume
#      (data.db) persists; the untracked .env / server/cert.pem / server/key.pem
#      are gitignored and therefore preserved across every pull.
#   4. Verifies the app is serving.
#
# Usage (on the server):
#   cd /opt/bizgaze-support
#   ./deploy.sh                # pull latest + rebuild
#   ./deploy.sh --no-pull      # rebuild current checkout (no git pull)
#   ./deploy.sh --rollback     # restore newest backup snapshot + rebuild
#
# Fire it from your laptop without logging in:
#   plink -ssh -P 61 -pw '<pw>' root@118.95.33.89 \
#     "cd /opt/bizgaze-support && ./deploy.sh"

set -euo pipefail

GIT_BRANCH="${GIT_BRANCH:-master}"
KEEP_BACKUPS="${KEEP_BACKUPS:-3}"
CONTAINER="${CONTAINER:-bizgaze-support}"

cd "$(dirname "$(readlink -f "$0")")"
APP_DIR="$(pwd)"
BK_DIR="${APP_DIR}.backups"

log() { printf '\033[1;36m==>\033[0m %s\n' "$*"; }
ok()  { printf '\033[1;32m  ✓\033[0m %s\n' "$*"; }
warn(){ printf '\033[1;33m  ! %s\033[0m\n' "$*"; }
die() { printf '\033[1;31mERROR:\033[0m %s\n' "$*" >&2; exit 1; }

[ -d .git ] || die "Not a git checkout. Run the one-time bootstrap first (see DEPLOY.md)."
command -v docker >/dev/null || die "docker not found on this host."

# --- args ---
DO_PULL=1; ROLLBACK=0
for a in "$@"; do case "$a" in
  --no-pull) DO_PULL=0 ;;
  --rollback) ROLLBACK=1 ;;
  -h|--help) grep '^#' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;;
  *) die "Unknown argument: $a" ;;
esac; done

snapshot() {
  mkdir -p "$BK_DIR"
  local ts rev
  ts="$(date +%Y%m%d-%H%M%S)"
  rev="$(git rev-parse --short HEAD 2>/dev/null || echo nogit)"
  log "Snapshot -> $BK_DIR/${ts}-${rev}.tgz"
  tar --exclude=./.git --exclude=./node_modules \
      --exclude=./server/node_modules -czf "$BK_DIR/${ts}-${rev}.tgz" -C "$APP_DIR" .
  # rotate: keep newest $KEEP_BACKUPS
  local old
  old="$(ls -1t "$BK_DIR"/*.tgz 2>/dev/null | tail -n +$((KEEP_BACKUPS + 1)) || true)"
  if [ -n "$old" ]; then
    echo "Pruning old backups:"; echo "$old" | sed 's/^/  rm /'
    echo "$old" | xargs -r rm -f
  fi
}

rebuild() {
  [ -f .env ] || warn "No .env present — TURN/SSO secrets will be unset."
  log "Rebuilding and recreating the container …"
  docker compose config >/dev/null || die "docker-compose.yml is invalid."
  docker compose up -d --build
  docker compose ps
}

verify() {
  log "Verifying /api/ice …"
  if docker exec "$CONTAINER" wget -qO- http://localhost:8090/api/ice 2>/dev/null | grep -q iceServers; then
    ok "App is serving."
  else
    warn "Could not confirm /api/ice — check: docker logs $CONTAINER"
  fi
}

# Recreating the app container can give it a NEW docker network IP. Nginx Proxy Manager caches the app's
# upstream IP at config-load, so it would keep hitting the OLD IP ("Connection refused" → site down) until
# it re-resolves. Reload NPM's nginx so it picks up the current IP. Non-fatal: warn (don't fail) if NPM
# isn't found — some environments run a different reverse proxy.
reload_proxy() {
  local npm
  npm="$(docker ps --format '{{.Names}}' | grep -iE 'nginx.?proxy.?manager.*app' | head -n1 || true)"
  if [ -n "$npm" ] && docker exec "$npm" nginx -t >/dev/null 2>&1; then
    if docker exec "$npm" nginx -s reload >/dev/null 2>&1; then
      ok "Reloaded $npm (re-resolved app upstream IP)."
    else
      warn "Could not reload $npm — if the site 502s, run: docker exec $npm nginx -s reload"
    fi
  else
    warn "Reverse proxy (NPM) not auto-detected; if the site fails after deploy, reload it so it re-resolves the app IP."
  fi
}

# --- rollback mode ---
if [ "$ROLLBACK" -eq 1 ]; then
  latest="$(ls -1t "$BK_DIR"/*.tgz 2>/dev/null | head -n1 || true)"
  [ -n "$latest" ] || die "No backups found in $BK_DIR"
  log "Rolling back from: $latest"
  snapshot                                   # snapshot the (broken) current state first
  tar -xzf "$latest" -C "$APP_DIR"
  rebuild; verify; reload_proxy
  ok "Rolled back to $latest"
  exit 0
fi

# --- normal deploy ---
snapshot
if [ "$DO_PULL" -eq 1 ]; then
  log "Fetching origin/$GIT_BRANCH …"
  git fetch origin "$GIT_BRANCH"
  git reset --hard "origin/$GIT_BRANCH"      # untracked .env / *.pem are preserved
  ok "Now at $(git rev-parse --short HEAD): $(git log -1 --pretty=%s)"
fi
rebuild
verify
reload_proxy
ok "Deploy complete. Backups kept: $KEEP_BACKUPS (in $BK_DIR)."
echo "   Rollback with:  ./deploy.sh --rollback"
