#!/usr/bin/env bash
#
# Dump the production Postgres database and restore it into the local
# `prop_dev`, replacing whatever is there. Pulls prod credentials from
# `.envrc` (direnv handles the export) so there is no duplicated config.
#
# Usage:
#
#   scripts/restore_prod_to_local.sh
#
# Before running: stop `mix phx.server` so Ecto doesn't hold connections.
# Requires direnv (or `source .envrc`) so PROP_PROD_DB_URL is set.

set -euo pipefail

: "${PROP_PROD_DB_URL:?not set — run via direnv or 'source .envrc' first}"

LOCAL_DB="${LOCAL_DB:-prop_dev}"
LOCAL_USER="${LOCAL_USER:-postgres}"
LOCAL_HOST="${LOCAL_HOST:-localhost}"
LOCAL_TMP="${LOCAL_TMP:-/tmp}"

# Prod runs Postgres 18; pg_dump refuses to talk to a newer server than
# its own version. Pin to the Homebrew @18 binaries so this works on a
# machine whose default PATH still points at an older series.
PG_BIN="${PG_BIN:-/opt/homebrew/opt/postgresql@18/bin}"
PG_DUMP="${PG_BIN}/pg_dump"
PG_RESTORE="${PG_BIN}/pg_restore"
PSQL="${PG_BIN}/psql"

timestamp=$(date -u +'%Y%m%d_%H%M%S')
dump_file="${LOCAL_TMP}/prop_prod_${timestamp}.dump"

log() {
    printf '%s restore_prod_to_local: %s\n' "$(date -u +'%Y-%m-%dT%H:%M:%SZ')" "$*"
}

die() {
    log "ERROR: $*"
    exit 1
}

[[ -x "$PG_DUMP" ]] || die "$PG_DUMP missing — brew install postgresql@18"
[[ -x "$PG_RESTORE" ]] || die "$PG_RESTORE missing — brew install postgresql@18"
[[ -x "$PSQL" ]] || die "$PSQL missing — brew install postgresql@18"

# Always remove the downloaded dump, even on mid-run failure. Keeps
# multi-GB dumps from accumulating in /tmp.
cleanup() {
    [[ -n "${dump_file:-}" && -f "$dump_file" ]] && rm -f "$dump_file"
}
trap cleanup EXIT

log "dumping prod -> ${dump_file}"
# --verbose streams per-object progress to stderr so the run isn't a
# black box against a multi-GB remote DB.
"$PG_DUMP" \
    --dbname="$PROP_PROD_DB_URL" \
    --format=custom \
    --compress=6 \
    --no-owner \
    --no-acl \
    --verbose \
    --file="$dump_file"

size=$(stat -f '%z' "$dump_file" 2>/dev/null || stat -c '%s' "$dump_file")
log "dump complete ($(numfmt --to=iec "$size" 2>/dev/null || echo "$size bytes"))"

# Kick any existing connections off the DB before dropping it — otherwise
# `DROP DATABASE` fails with "is being accessed by other users".
log "terminating existing connections to ${LOCAL_DB}"
"$PSQL" -h "$LOCAL_HOST" -U "$LOCAL_USER" -d postgres -v ON_ERROR_STOP=1 <<SQL >/dev/null
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE datname = '${LOCAL_DB}' AND pid <> pg_backend_pid();
SQL

log "dropping and recreating ${LOCAL_DB}"
"$PSQL" -h "$LOCAL_HOST" -U "$LOCAL_USER" -d postgres -v ON_ERROR_STOP=1 <<SQL >/dev/null
DROP DATABASE IF EXISTS ${LOCAL_DB};
CREATE DATABASE ${LOCAL_DB} OWNER ${LOCAL_USER};
SQL

# -j 4 parallelises table data restore; --verbose prints each object as
# workers pick it up so progress is visible.
log "restoring into ${LOCAL_DB}"
"$PG_RESTORE" \
    -h "$LOCAL_HOST" \
    -U "$LOCAL_USER" \
    -d "$LOCAL_DB" \
    --no-owner \
    --no-acl \
    --verbose \
    -j 4 \
    "$dump_file"

log "done — ${LOCAL_DB} now mirrors prod as of ${timestamp}"
