#!/usr/bin/env bash
# sync-prod-db.sh
#
# Dumps the production database and restores it to the development database,
# then sanitizes the copy to prevent outbound notifications and reduce PII exposure.
#
# Usage:
#   Add PROD_DATABASE_URL to your .env file, then:
#     npm run db:sync-prod
#   # or pass inline:
#     PROD_DATABASE_URL="postgres://..." npm run db:sync-prod
#   # or pass as argument:
#     bash scripts/sync-prod-db.sh "postgres://..."
#
# Requirements: pg_dump, pg_restore, psql (PostgreSQL client tools)

set -euo pipefail

# ── Colour helpers ────────────────────────────────────────────────────────────
RED='\033[0;31m'
YELLOW='\033[1;33m'
GREEN='\033[0;32m'
BOLD='\033[1m'
RESET='\033[0m'

info()    { echo -e "${BOLD}$*${RESET}"; }
warn()    { echo -e "${YELLOW}$*${RESET}"; }
success() { echo -e "${GREEN}$*${RESET}"; }
error()   { echo -e "${RED}ERROR: $*${RESET}" >&2; exit 1; }

# ── Check required tools (fix #5) ────────────────────────────────────────────
for cmd in pg_dump pg_restore psql; do
  command -v "$cmd" &>/dev/null || error "'$cmd' not found. Install PostgreSQL client tools (e.g. brew install libpq)."
done

# ── Load .env ─────────────────────────────────────────────────────────────────
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ENV_FILE="$SCRIPT_DIR/../.env"

if [[ -f "$ENV_FILE" ]]; then
  # Export DATABASE_URL and PROD_DATABASE_URL from .env if not already set in the environment
  DATABASE_URL_FROM_ENV=$(grep -E '^DATABASE_URL=' "$ENV_FILE" | head -1 | cut -d= -f2- | sed 's/^"//' | sed 's/"$//')
  if [[ -n "$DATABASE_URL_FROM_ENV" && -z "${DATABASE_URL:-}" ]]; then
    export DATABASE_URL="$DATABASE_URL_FROM_ENV"
  fi

  PROD_DATABASE_URL_FROM_ENV=$(grep -E '^PROD_DATABASE_URL=' "$ENV_FILE" | head -1 | cut -d= -f2- | sed 's/^"//' | sed 's/"$//')
  if [[ -n "$PROD_DATABASE_URL_FROM_ENV" && -z "${PROD_DATABASE_URL:-}" ]]; then
    export PROD_DATABASE_URL="$PROD_DATABASE_URL_FROM_ENV"
  fi
fi

# ── Resolve URLs ──────────────────────────────────────────────────────────────
# PROD_DATABASE_URL: env var or first positional argument
PROD_DB="${PROD_DATABASE_URL:-${1:-}}"
DEV_DB="${DATABASE_URL:-}"

[[ -z "$PROD_DB" ]] && error "PROD_DATABASE_URL is not set.\nSet it as an environment variable or pass it as the first argument:\n  PROD_DATABASE_URL=\"postgres://...\" npm run db:sync-prod"
[[ -z "$DEV_DB"  ]] && error "DATABASE_URL is not set. Add it to your .env file."

# Guard against accidentally syncing prod → prod
if [[ "$PROD_DB" == "$DEV_DB" ]]; then
  error "PROD_DATABASE_URL and DATABASE_URL are the same. Aborting to prevent data loss."
fi

# ── Mask password for display (fix #6) ───────────────────────────────────────
# Replaces only the password portion (between : and @) using sed, not bash globs.
mask_url() {
  echo "$1" | sed 's|\(://[^:]*\):[^@]*@|\1:***@|'
}

# ── Confirmation prompt ───────────────────────────────────────────────────────
echo ""
warn "⚠️  WARNING: This will OVERWRITE your development database with production data."
echo ""
echo -e "  Source (prod):  ${BOLD}$(mask_url "$PROD_DB")${RESET}"
echo -e "  Target (dev):   ${BOLD}$(mask_url "$DEV_DB")${RESET}"
echo ""
warn "After restore, the script will:"
echo "  • NULL out all Discord webhook URLs (prevents notification leaks)"
echo "  • Anonymize email/name/avatar for non-admin users (reduces PII exposure)"
echo "  • Admin accounts are left untouched so you can still access admin pages"
echo ""
read -r -p "Type 'yes' to continue: " CONFIRM
if [[ "$CONFIRM" != "yes" ]]; then
  echo "Aborted."
  exit 0
fi

# ── Dump ──────────────────────────────────────────────────────────────────────
DUMP_FILE=$(mktemp /tmp/brackt_prod_dump_XXXXXX.dump)
# Ensure the temp file is cleaned up on exit
trap 'rm -f "$DUMP_FILE"' EXIT

info ""
info "1/3  Dumping production database…"
pg_dump \
  --no-owner \
  --no-acl \
  --format=custom \
  "$PROD_DB" \
  --file="$DUMP_FILE"
success "     Dump complete: $(du -h "$DUMP_FILE" | cut -f1)"

# ── Restore (fix #1, #2, #3) ─────────────────────────────────────────────────
# Uses --clean --if-exists to drop and recreate all objects within the existing
# database, without needing DROP DATABASE / CREATE DATABASE permissions.
# This works on managed cloud databases (Railway, Render, Neon, Supabase, etc.).
#
# pg_restore exits with code 1 for non-fatal warnings (e.g. "role X does not
# exist" with --no-owner), so we capture the exit code and only abort on
# unexpected failures, not routine restore warnings.
info ""
info "2/3  Restoring production dump to development database…"
RESTORE_EXIT=0
pg_restore \
  --no-owner \
  --no-acl \
  --clean \
  --if-exists \
  --dbname="$DEV_DB" \
  "$DUMP_FILE" || RESTORE_EXIT=$?

if [[ $RESTORE_EXIT -eq 0 ]]; then
  success "     Restore complete."
elif [[ $RESTORE_EXIT -eq 1 ]]; then
  warn "     Restore completed with warnings (non-fatal). Continuing…"
else
  error "pg_restore failed with exit code $RESTORE_EXIT. Aborting."
fi

# ── Sanitize (fix #4) ────────────────────────────────────────────────────────
info ""
info "3/3  Sanitizing development database…"

SANITIZE_RESULT=$(psql "$DEV_DB" --tuples-only --no-align << 'SQL'
BEGIN;

-- 1. Count leagues with webhooks before clearing (accurate count)
SELECT 'discord_webhooks_nulled:' || COUNT(*) FROM leagues WHERE discord_webhook_url IS NOT NULL;
UPDATE leagues SET discord_webhook_url = NULL;

-- 2. Anonymize PII for non-admin users only
--    (admin accounts are untouched so admin pages remain accessible)
UPDATE users SET
  email        = 'user_' || id || '@example.com',
  display_name = 'Test User',
  image_url    = NULL
WHERE is_admin = FALSE;
SELECT 'users_anonymized:' || COUNT(*) FROM users WHERE is_admin = FALSE;

SELECT 'admin_users_kept:' || COUNT(*) FROM users WHERE is_admin = TRUE;

COMMIT;
SQL
)

LEAGUES_COUNT=$(echo "$SANITIZE_RESULT" | grep 'discord_webhooks_nulled:' | cut -d: -f2 | tr -d ' ')
ANON_COUNT=$(echo "$SANITIZE_RESULT"    | grep 'users_anonymized:'        | cut -d: -f2 | tr -d ' ')
ADMIN_COUNT=$(echo "$SANITIZE_RESULT"   | grep 'admin_users_kept:'        | cut -d: -f2 | tr -d ' ')

echo ""
success "✓ Sync complete. Sanitization summary:"
echo "  • Discord webhook URLs cleared: ${LEAGUES_COUNT:-?} leagues"
echo "  • Non-admin users anonymized:   ${ANON_COUNT:-?} users"
echo "  • Admin accounts preserved:     ${ADMIN_COUNT:-?} users"
echo ""
warn "Reminder: ensure your .env does NOT contain:"
echo "  • RESEND_API_KEY    (email sending)"
echo "  • SENTRY_AUTH_TOKEN (error tracking)"
echo "  • Production Clerk keys (use dev Clerk instance)"
echo ""
