#!/usr/bin/env bash
# =============================================================================
# Backup completo de los proyectos Supabase de Kynda.
#
# Cubre las tres exigencias del Anexo I, apartado 3.2, que hoy figuran como
# incumplidas: copia de la base de datos, copia de los ficheros de Storage (que
# las copias automáticas de Supabase NO incluyen) y verificación comprobable.
#
# Usa pg_dump directamente y NO la CLI de Supabase, porque esta última exige
# tener Docker en marcha. Comprobado: con la CLI el volcado falla si el demonio
# de Docker no está corriendo.
#
# Uso:   ./backup-supabase.sh
# Requiere: ~/Desktop/KYNDA/.backup-creds  (ver README-BACKUP.md)
# =============================================================================
set -uo pipefail

CREDS="${HOME}/Desktop/KYNDA/.backup-creds"
STAMP="$(date +%Y-%m-%d_%H%M)"
DEST="${HOME}/Desktop/KYNDA/backup-supabase-${STAMP}"
BIN="/opt/homebrew/opt/libpq/bin"
PGDUMP="${BIN}/pg_dump"; [ -x "$PGDUMP" ] || PGDUMP="$(command -v pg_dump || true)"
PSQL="${BIN}/psql";      [ -x "$PSQL" ]   || PSQL="$(command -v psql || true)"

# Esquemas propios del proyecto. Los gestionados por Supabase (extensions,
# realtime, vault, graphql...) se excluyen: no son restaurables ni nuestros.
ESQUEMAS=(public auth storage kynda)

rojo()  { printf '\033[31m%s\033[0m\n' "$*"; }
verde() { printf '\033[32m%s\033[0m\n' "$*"; }
info()  { printf '  %s\n' "$*"; }

[ -f "$CREDS" ] || { rojo "No existe $CREDS"; echo "Créalo siguiendo README-BACKUP.md"; exit 1; }
[ -x "$PGDUMP" ] || { rojo "pg_dump no encontrado"; exit 1; }

chmod 600 "$CREDS" 2>/dev/null
# shellcheck disable=SC1090
set -a; source "$CREDS"; set +a

echo "Destino: $DEST"
mkdir -p "$DEST"
FALLOS_TOTALES=0

volcar() {
  local nombre="$1" url="$2" key="$3" ref="$4"
  local dir="${DEST}/${nombre}"

  echo ""
  echo "=============================================================="
  echo " Proyecto: $nombre   ($ref)"
  echo "=============================================================="

  if [ -z "${url:-}" ]; then info "sin cadena de conexión, se omite"; return; fi
  mkdir -p "$dir/storage"

  # --- Conexión: se comprueba de verdad, con una consulta real ---------------
  info "Comprobando conexión..."
  local ver
  if ! ver="$("$PSQL" "$url" -tAc 'select version()' 2>"$dir/.err")"; then
    rojo "  NO se pudo conectar:"
    sed 's/^/    /' "$dir/.err" | head -3
    FALLOS_TOTALES=$((FALLOS_TOTALES+1))
    return
  fi
  rm -f "$dir/.err"
  verde "  conectado: $(echo "$ver" | cut -c1-40)"

  # Qué esquemas existen realmente en este proyecto
  local presentes=() s
  for s in "${ESQUEMAS[@]}"; do
    if [ "$("$PSQL" "$url" -tAc "select 1 from information_schema.schemata where schema_name='$s'" 2>/dev/null)" = "1" ]; then
      presentes+=("$s")
    fi
  done
  info "Esquemas a copiar: ${presentes[*]}"
  local args=(); for s in "${presentes[@]}"; do args+=(--schema="$s"); done

  # --- 1) Estructura: tablas, funciones, triggers, políticas de seguridad ----
  info "Volcando estructura..."
  if "$PGDUMP" "$url" --schema-only --no-owner --no-privileges "${args[@]}" -f "$dir/estructura.sql" 2>"$dir/.err"; then
    verde "  estructura: $(du -h "$dir/estructura.sql" | cut -f1)"
  else
    rojo "  fallo en estructura:"; sed 's/^/    /' "$dir/.err" | head -3; FALLOS_TOTALES=$((FALLOS_TOTALES+1))
  fi

  # --- 2) Datos -------------------------------------------------------------
  info "Volcando datos..."
  if "$PGDUMP" "$url" --data-only --no-owner --no-privileges --disable-triggers "${args[@]}" -f "$dir/datos.sql" 2>"$dir/.err"; then
    verde "  datos: $(du -h "$dir/datos.sql" | cut -f1)"
  else
    rojo "  fallo en datos:"; sed 's/^/    /' "$dir/.err" | head -3; FALLOS_TOTALES=$((FALLOS_TOTALES+1))
  fi

  # --- 3) Copia completa en formato comprimido (la que se usa para restaurar)
  info "Volcando copia comprimida restaurable..."
  if "$PGDUMP" "$url" --format=custom --no-owner --no-privileges "${args[@]}" -f "$dir/completo.dump" 2>"$dir/.err"; then
    verde "  completo.dump: $(du -h "$dir/completo.dump" | cut -f1)"
  else
    rojo "  fallo en copia comprimida:"; sed 's/^/    /' "$dir/.err" | head -3
  fi
  rm -f "$dir/.err"

  # --- 4) Ficheros de Storage ------------------------------------------------
  if [ -n "${key:-}" ]; then
    info "Descargando ficheros de Storage..."
    SUPABASE_URL="https://${ref}.supabase.co" SUPABASE_KEY="$key" DEST_DIR="$dir/storage" \
      node "$(cd "$(dirname "$0")" && pwd)/descargar-storage.mjs" 2>&1 | sed 's/^/    /'
  else
    rojo "  sin clave de servicio: los ficheros de Storage NO se descargan"
    FALLOS_TOTALES=$((FALLOS_TOTALES+1))
  fi

  # --- 5) Manifiesto verificable --------------------------------------------
  info "Generando manifiesto..."
  {
    echo "MANIFIESTO DE BACKUP — $nombre"
    echo "Fecha:     $(date '+%Y-%m-%d %H:%M:%S %Z')"
    echo "Proyecto:  $ref"
    echo "Servidor:  $ver"
    echo ""
    echo "FICHEROS"
    for f in estructura.sql datos.sql completo.dump; do
      if [ -f "$dir/$f" ]; then
        printf "  %-18s %8s  sha256:%s\n" "$f" "$(du -h "$dir/$f" | cut -f1)" "$(shasum -a 256 "$dir/$f" | cut -c1-16)"
      else
        printf "  %-18s AUSENTE\n" "$f"
      fi
    done
    echo ""
    echo "STORAGE"
    echo "  ficheros: $(find "$dir/storage" -type f ! -name INVENTARIO.tsv 2>/dev/null | wc -l | tr -d ' ')"
    echo "  tamaño:   $(du -sh "$dir/storage" 2>/dev/null | cut -f1)"
    echo ""
    echo "RECUENTO DE FILAS EN ORIGEN (para verificar la restauración)"
    "$PSQL" "$url" -tA -F'  ' -c "
      select schemaname||'.'||relname, n_live_tup
        from pg_stat_user_tables
       where schemaname in ('public','auth','storage','kynda')
         and n_live_tup > 0
       order by 1" 2>/dev/null | sed 's/^/  /'
  } > "$dir/MANIFIESTO.txt"
  verde "  manifiesto listo"
}

volcar "produccion" "${PROD_DB_URL:-}" "${PROD_SERVICE_KEY:-}" "${PROD_REF:-lfgaaijrzkufkbxwhmjz}"
volcar "validacion" "${CERT_DB_URL:-}" "${CERT_SERVICE_KEY:-}" "${CERT_REF:-lovcrkoofqffhdclxaxg}"

echo ""
echo "=============================================================="
if [ "$FALLOS_TOTALES" -eq 0 ]; then verde " Backup terminado sin incidencias"; else rojo " Backup terminado con $FALLOS_TOTALES incidencia(s): revisa arriba"; fi
echo "=============================================================="
echo " Ubicación: $DEST"
echo " Tamaño:    $(du -sh "$DEST" 2>/dev/null | cut -f1)"
echo ""
echo " Para restaurar en un proyecto nuevo:"
echo "   pg_restore --no-owner --no-privileges -d <URL_DESTINO> completo.dump"
echo ""
echo " Guarda una copia FUERA de este equipo. Una copia en el mismo disco"
echo " que el original no es una copia de seguridad."
exit $(( FALLOS_TOTALES > 0 ? 1 : 0 ))
