#!/usr/bin/env bash
# The staging dump the launch replaces production with (Stream K7; plan W17). Run on the dev server,
# with every collection frozen:
#
#     deploy/launch-dump.sh                                   # staging: dutyfreeprofessor-db / dfp
#     deploy/launch-dump.sh --db-container dfp-devdb --db dfp_k7_staging --out backups/launch/x.dump
#
# Writes, side by side:
#   <out>          pg_dump -Fc of the database
#   <out>.counts   "table<TAB>rows" for every table in public, exact count(*), sorted
#   <out>.head     the alembic_version the dump carries
#   <out>.sources  every source's switch, delay, identity mode and permission record, for rian to
#                  confirm against production after the replace
# The counts are taken before and after the dump and must agree: a write during the dump would make
# the sidecar describe a database the dump does not hold, and the replace would then refuse on a
# difference nobody could explain. `deploy/production.sh --replace-db <out>` reads all three.
set -euo pipefail

CONTAINER=dutyfreeprofessor-db
DB=dfp
OUT=""
while [ $# -gt 0 ]; do
  case "$1" in
    --db-container) CONTAINER="$2"; shift 2 ;;
    --db) DB="$2"; shift 2 ;;
    --out) OUT="$2"; shift 2 ;;
    -h|--help) sed -n '2,17p' "$0"; exit 0 ;;
    *) echo "unknown argument: $1" >&2; exit 2 ;;
  esac
done

cd "$(dirname "$0")/.."
[ -n "$OUT" ] || OUT="backups/launch/staging-$(date -u +%Y-%m-%d-%H%M).dump"
mkdir -p "$(dirname "$OUT")"

psql_q() { docker exec -i "$CONTAINER" psql -U dfp -d "$DB" -v ON_ERROR_STOP=1 -tA -F $'\t' -c "$1"; }

# Every table in public with its exact row count: one generated UNION, so the numbers are one snapshot.
counts() {
  local tables sql=""
  tables=$(psql_q "select table_name from information_schema.tables where table_schema = 'public' and table_type = 'BASE TABLE' order by table_name")
  for t in $tables; do
    sql+="${sql:+ union all }select '$t', count(*) from public.\"$t\""
  done
  psql_q "$sql" | sort
}

if pgrep -af 'app.cli (collect|verify)' >/dev/null 2>&1; then
  echo "REFUSED: a collection or verify is running on this machine; freeze collections first (RUNBOOK 'Launch checklist')." >&2
  exit 1
fi

before=$(counts)
docker exec "$CONTAINER" pg_dump -U dfp -Fc "$DB" > "$OUT"
after=$(counts)
if [ "$before" != "$after" ]; then
  echo "REFUSED: rows changed while the dump ran; the dump is not a snapshot. Freeze writes and run again:" >&2
  diff <(printf '%s\n' "$before") <(printf '%s\n' "$after") >&2 || true
  rm -f "$OUT"
  exit 1
fi
printf '%s\n' "$after" > "$OUT.counts"
psql_q "select version_num from alembic_version" > "$OUT.head"
psql_q "select slug, enabled, delay_seconds, identity_mode, coalesce(permission_record, '') from sources order by slug" > "$OUT.sources"

echo "dump:    $OUT ($(du -h "$OUT" | cut -f1))"
echo "tables:  $(wc -l < "$OUT.counts"), rows $(awk -F'\t' '{s += $2} END {print s}' "$OUT.counts")"
echo "head:    $(cat "$OUT.head")"
echo "sources: $(wc -l < "$OUT.sources") ($(awk -F'\t' '$2 == "t"' "$OUT.sources" | wc -l) enabled)"
