#!/usr/bin/env bash
# Tx OS — redeploy after `git pull` on the Mac (or any Docker host).
#
# Why this exists:
#   The SPA is baked into the `web` (nginx) image at build time, and the
#   API binary is baked into the `api` image. `docker compose up -d` on
#   its own re-uses the existing images, so a plain `git pull` will NOT
#   pick up new front-end assets (e.g. service tile images), code
#   changes, or DB-seed updates.
#
# What it does:
#   1. git pull           — fast-forward the working tree (skipped with --no-pull)
#   2. docker compose build api web
#                          — rebuild both images so source + static assets are fresh
#   3. docker compose run --rm migrate
#                          — apply Drizzle schema (migrate.sh also runs the seed,
#                            but tolerates seed failures — see step 4)
#   4. docker compose run --rm --entrypoint "" --no-deps migrate \
#        pnpm --filter @workspace/scripts run seed
#                          — explicit seed pass that fails hard if the seed
#                            errors. Catches new-app / renamed-app regressions
#                            that migrate.sh would otherwise swallow.
#   5. docker compose up -d
#                          — restart api + web with the new images
#
# Safe to re-run. Each step is idempotent.

set -euo pipefail

PULL=1
for arg in "$@"; do
  case "$arg" in
    --no-pull) PULL=0 ;;
    -h|--help)
      sed -n '2,27p' "$0"
      exit 0
      ;;
    *)
      echo "Unknown argument: $arg" >&2
      echo "Usage: $0 [--no-pull]" >&2
      exit 2
      ;;
  esac
done

# Resolve the repo root so the script works no matter where it's invoked from.
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
cd "$REPO_ROOT"

if [ ! -f docker-compose.yml ]; then
  echo "[redeploy] error: docker-compose.yml not found in $REPO_ROOT" >&2
  exit 1
fi

if ! command -v docker >/dev/null 2>&1; then
  echo "[redeploy] error: docker CLI not found in PATH" >&2
  exit 1
fi

# Pick `docker compose` (v2) and fall back to `docker-compose` (v1) so this
# works on older hosts.
if docker compose version >/dev/null 2>&1; then
  DC=(docker compose)
elif command -v docker-compose >/dev/null 2>&1; then
  DC=(docker-compose)
else
  echo "[redeploy] error: neither 'docker compose' nor 'docker-compose' is available" >&2
  exit 1
fi

step() { echo; echo "==> $*"; }

if [ "$PULL" -eq 1 ]; then
  step "1/6  git pull"
  git pull --ff-only
else
  step "1/6  git pull (skipped via --no-pull)"
fi

step "2/6  docker compose build api web  (rebuilds SPA + API images)"
# Stamp the API image with the current git SHA + UTC build time so the
# admin "System Updates" panel shows visible proof that the new image
# is actually running (instead of the old, hand-edited version.json).
# Both are read inside docker/api-server.Dockerfile as ARGs.
export GIT_SHA="$(git rev-parse --short HEAD 2>/dev/null || echo unknown)"
export BUILD_DATE="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
echo "[redeploy]   GIT_SHA=$GIT_SHA  BUILD_DATE=$BUILD_DATE"
"${DC[@]}" build api web

step "3/6  docker compose run --rm migrate  (schema push + tolerant seed)"
"${DC[@]}" run --rm migrate

step "4/6  explicit seed pass (fails hard on seed regressions)"
"${DC[@]}" run --rm --no-deps --entrypoint "" migrate \
  pnpm --filter @workspace/scripts run seed

step "5/6  one-shot data migrations (idempotent)"
# #603: bump seeded app tile colours on existing installs. The seed
# step above uses onConflictDoNothing for `slug`, so already-seeded
# rows keep their old colours forever without this. The script only
# touches rows that still hold the OLD default — admin customisations
# from the Apps editor are left alone.
"${DC[@]}" run --rm --no-deps --entrypoint "" migrate \
  pnpm --filter @workspace/scripts run update-app-colors

step "6/6  docker compose up -d  (restart with the new images)"
"${DC[@]}" up -d

echo
echo "[redeploy] done. Verify in a browser; hard-refresh once to bust the SPA cache."
