#!/usr/bin/env bash
# =============================================================================
#  delete-project.sh — Elimina un proyecto BewPro/CD-System completamente
#  Diseñado para ser invocado desde el panel web via webhook o artisan.
#
#  Capas de limpieza (en orden):
#    1. Airtable lookup  — busca PROJECT_ID, SERVER, Subscription IDs
#    2. Backup MySQL     — mysqldump + gzip → Backblaze via WHM (si --backup)
#    3. VPS account      — HestiaCP (v-delete-user) o cPanel (removeacct)
#    4. Cloudinary       — DELETE assets + folder via API REST
#    5. DNS Hostinger    — DELETE record A via API
#    6. Airtable delete  — DELETE Project + Subscriptions (no solo PATCH)
#
#  Uso:
#    /root/scripts/delete-project.sh <cpanel_user> [opciones]
#
#  Opciones:
#    --backup              Hacer backup MySQL → Backblaze antes de eliminar
#    --skip-backup         Alias explícito de "sin backup" (default)
#    --dry-run             Preview sin ejecutar cambios
#    --yes                 Sin confirmación interactiva
#    --keep-airtable       Preservar registros Airtable (solo limpia VPS/DNS/Cloudinary)
#    --server=vps1|vps2    Forzar servidor (default: auto-detectar via Airtable)
#    --cloudinary-folder=  Folder Cloudinary a limpiar (default: cpanel_user)
#    --reason=             Motivo del borrado (queda en logs)
#
#  Config:
#    /root/scripts/.airtable.env  — vars de entorno (ver sección CONFIG FILE)
#
#  Salida:
#    exit 0 → todo OK (o dry-run)
#    exit 1 → al menos un paso falló
#    exit 2 → error de argumentos / config
# =============================================================================

set -uo pipefail
export PATH="/usr/local/hestia/bin:/usr/local/bin:/usr/bin:/bin:$PATH"

# ─── Colores ──────────────────────────────────────────────────────────────────
GREEN='\033[0;32m'; RED='\033[0;31m'; YELLOW='\033[1;33m'
CYAN='\033[0;36m'; BOLD='\033[1m'; NC='\033[0m'
ok()   { echo -e "  ${GREEN}✓${NC} $*"; }
fail() { echo -e "  ${RED}✗${NC} $*" >&2; }
warn() { echo -e "  ${YELLOW}⚠${NC} $*" >&2; }
info() { echo -e "  ${CYAN}→${NC} $*"; }

# ─── Usuarios y servidores protegidos ─────────────────────────────────────────
PROTECTED_USERS=("admin" "bewpro" "root")

# ─── IPs de los VPS ───────────────────────────────────────────────────────────
VPS1_NAME="VPS Hostinger 1"   # Local (cPanel/WHM — donde corre este script)
VPS2_IP="179.43.124.219"
VPS2_PORT="5633"
VPS2_NAME="VPS Donweb 1"      # cPanel/WHM via SSH
VPS3_IP="179.43.120.113"
VPS3_PORT="5651"
VPS3_NAME="VPS Donweb 2"      # HestiaCP via SSH

BACKUP_STAGING_DIR="${BACKUP_STAGING_DIR:-/backup/pre-delete}"

# ─── Progreso (leído por el webhook /status endpoint) ─────────────────────────
PROGRESS_FILE=""  # se asigna después de parsear CPANEL_USER

write_progress() {
  # write_progress <step> <status: pending|running|done|error> [detail]
  [[ -z "$PROGRESS_FILE" ]] && return
  local step="$1" status="$2" detail="${3:-}"
  local now; now=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
  python3 -c "
import json, sys, os
pf, step, status, detail, now = sys.argv[1:]
try:
    with open(pf) as f: data = json.load(f)
except:
    data = {}
data.setdefault('steps', {})
data['steps'][step] = {'status': status, 'detail': detail}
data['updated_at'] = now
with open(pf, 'w') as f: json.dump(data, f)
try: os.chmod(pf, 0o644)
except: pass
" "$PROGRESS_FILE" "$step" "$status" "$detail" "$now" 2>/dev/null || true
}

# =============================================================================
# ARGUMENTOS
# =============================================================================

CPANEL_USER=""
WITH_BACKUP=false
DRY_RUN=false
AUTO_CONFIRM=false
KEEP_AIRTABLE=false
FORCE_SERVER=""
CLOUDINARY_FOLDER_OVERRIDE=""
REASON="Eliminado desde panel BewPro"
AIRTABLE_PROJECT_ID_OVERRIDE=""
DOMAIN_OVERRIDE=""   # dominio completo, ej: parrilla-don-ferro.bewpro.com

usage() {
  echo "Uso: $0 <cpanel_user> [--backup] [--dry-run] [--yes] [--keep-airtable]"
  echo "         [--server=vps1|vps2|vps3] [--cloudinary-folder=PATH] [--reason=STR]"
  echo "         [--airtable-project-id=recXXX] [--domain=FQDN]"
}

while (($#)); do
  case "$1" in
    --backup)               WITH_BACKUP=true;                                       shift ;;
    --skip-backup)          WITH_BACKUP=false;                                      shift ;;
    --dry-run)              DRY_RUN=true;                                           shift ;;
    --yes)                  AUTO_CONFIRM=true;                                      shift ;;
    --keep-airtable)        KEEP_AIRTABLE=true;                                     shift ;;
    --server=*)             FORCE_SERVER="${1#--server=}";                          shift ;;
    --cloudinary-folder=*)  CLOUDINARY_FOLDER_OVERRIDE="${1#--cloudinary-folder=}"; shift ;;
    --reason=*)             REASON="${1#--reason=}";                                shift ;;
    --airtable-project-id=*)AIRTABLE_PROJECT_ID_OVERRIDE="${1#--airtable-project-id=}"; shift ;;
    --domain=*)             DOMAIN_OVERRIDE="${1#--domain=}";                       shift ;;
    -h|--help)              usage; exit 0 ;;
    -*)                     fail "Opción no reconocida: $1"; usage; exit 2 ;;
    *)
      if [[ -z "$CPANEL_USER" ]]; then
        CPANEL_USER="$1"
      else
        fail "Parámetro inesperado: $1"; usage; exit 2
      fi
      shift ;;
  esac
done

if [[ -z "$CPANEL_USER" ]]; then
  fail "Debes indicar un cpanel_user."; usage; exit 2
fi

# Guard: protegidos
for p in "${PROTECTED_USERS[@]}"; do
  if [[ "$CPANEL_USER" == "$p" ]]; then
    fail "Usuario protegido '${CPANEL_USER}' — operación cancelada."; exit 2
  fi
done

# Inicializar archivo de progreso (legible por www-data via el webhook /status)
PROGRESS_FILE="/tmp/bewpro-delete-${CPANEL_USER}.json"
python3 -c "
import json, os
data = {
  'cpanel_user': '$CPANEL_USER',
  'started_at': __import__('datetime').datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ'),
  'done': False,
  'error': None,
  'steps': {
    'vps':        {'status': 'pending', 'detail': ''},
    'cloudinary': {'status': 'pending', 'detail': ''},
    'dns':        {'status': 'pending', 'detail': ''},
    'airtable':   {'status': 'pending', 'detail': ''},
  }
}
with open('$PROGRESS_FILE', 'w') as f: json.dump(data, f)
os.chmod('$PROGRESS_FILE', 0o644)
" 2>/dev/null || true

# =============================================================================
# CONFIG FILE
# =============================================================================
# Formato esperado en /root/scripts/.airtable.env:
#
#   AIRTABLE_TOKEN=patXXX...
#   AIRTABLE_BASE_ID=appXXX...
#   AIRTABLE_TABLE_ID=tblXXX...                   # tabla Projects
#   AIRTABLE_SUBSCRIPTIONS_TRACKING_TABLE=tblXXX...
#   HOSTINGER_TOKEN=...
#   CLOUDINARY_CLOUD_NAME=dupf7vvwj
#   CLOUDINARY_API_KEY=413378447996456
#   CLOUDINARY_API_SECRET=pslFZxYtoWaGWj4IcvGSb26r1hw

CONFIG_FILE="/root/scripts/.airtable.env"
[[ -f "$CONFIG_FILE" ]] && source "$CONFIG_FILE"

AIRTABLE_TOKEN="${AIRTABLE_TOKEN:-}"
AIRTABLE_BASE_ID="${AIRTABLE_BASE_ID:-}"
AIRTABLE_PROJECTS_TABLE="${AIRTABLE_TABLE_ID:-}"
AIRTABLE_SUBS_TABLE="${AIRTABLE_SUBSCRIPTIONS_TRACKING_TABLE:-tblnpr52JhFBBi2Mg}"
HOSTINGER_TOKEN="${HOSTINGER_TOKEN:-}"
HOSTINGER_DNS_ZONE="bewpro.com"
CLOUDINARY_CLOUD_NAME="${CLOUDINARY_CLOUD_NAME:-dupf7vvwj}"
CLOUDINARY_API_KEY="${CLOUDINARY_API_KEY:-413378447996456}"
CLOUDINARY_API_SECRET="${CLOUDINARY_API_SECRET:-pslFZxYtoWaGWj4IcvGSb26r1hw}"

API_BASE=""
[[ -n "$AIRTABLE_TOKEN" && -n "$AIRTABLE_BASE_ID" ]] && \
  API_BASE="https://api.airtable.com/v0/${AIRTABLE_BASE_ID}"

CLOUDINARY_BASE="https://api.cloudinary.com/v1_1/${CLOUDINARY_CLOUD_NAME}"

# Resolver subdominio y folder Cloudinary desde --domain si viene, si no fallback a cpanel_user
# --domain puede ser "parrilla-don-ferro.bewpro.com" o "parrilla-don-ferro.bewpro.com/"
DOMAIN_CLEAN="${DOMAIN_OVERRIDE%%/*}"       # quitar trailing slash
DOMAIN_CLEAN="${DOMAIN_CLEAN#https://}"     # quitar protocolo si alguien lo mandó
DOMAIN_CLEAN="${DOMAIN_CLEAN#http://}"
SUBDOMAIN_FROM_DOMAIN="${DOMAIN_CLEAN%%.*}" # extraer parte antes del primer punto

# DNS: usar subdominio real si está disponible, sino cpanel_user
DNS_SUBDOMAIN="${SUBDOMAIN_FROM_DOMAIN:-$CPANEL_USER}"

# Cloudinary folder: manual override > subdominio real > cpanel_user
CLOUDINARY_FOLDER="${CLOUDINARY_FOLDER_OVERRIDE:-${SUBDOMAIN_FROM_DOMAIN:-$CPANEL_USER}}"

# =============================================================================
# HEADER
# =============================================================================

echo ""
echo -e "${BOLD}════════════════════════════════════════════${NC}"
echo -e "${BOLD}  DELETE PROJECT: ${CPANEL_USER}${NC}"
echo -e "${BOLD}════════════════════════════════════════════${NC}"
[[ "$DRY_RUN"      == "true" ]] && echo -e "  ${YELLOW}⚠  DRY RUN — nada se ejecuta${NC}"
[[ "$WITH_BACKUP"  == "true" ]] && echo "  Backup    : MySQL → Backblaze habilitado"
[[ "$WITH_BACKUP"  == "false" ]] && echo "  Backup    : deshabilitado (--skip-backup)"
[[ "$KEEP_AIRTABLE" == "true" ]] && echo "  Airtable  : se conserva (--keep-airtable)"
echo "  DNS sub   : ${DNS_SUBDOMAIN}.${HOSTINGER_DNS_ZONE}"
echo "  Cloudinary: ${CLOUDINARY_FOLDER}"
echo "  Motivo    : ${REASON}"
echo ""

ERRORS=0

# =============================================================================
# UTILIDADES
# =============================================================================

urlencode() {
  python3 -c "import sys,urllib.parse; print(urllib.parse.quote(sys.argv[1], safe=''))" "$1"
}

_ssh_opts="-o StrictHostKeyChecking=no -o ConnectTimeout=15 -o BatchMode=yes"

remote_exec() {
  local sname="$1"; shift
  case "$sname" in
    "$VPS1_NAME") bash -c "$*" ;;
    "$VPS2_NAME") ssh $_ssh_opts -p "${VPS2_PORT}" root@${VPS2_IP} "$*" ;;
    "$VPS3_NAME") ssh $_ssh_opts -p "${VPS3_PORT}" root@${VPS3_IP} "$*" ;;
    *) fail "remote_exec: servidor desconocido '${sname}'"; return 1 ;;
  esac
}

remote_file_exists() {
  local sname="$1" path="$2"
  case "$sname" in
    "$VPS1_NAME") [[ -e "$path" ]] ;;
    "$VPS2_NAME") ssh $_ssh_opts -p "${VPS2_PORT}" root@${VPS2_IP} "test -e '${path}'" 2>/dev/null ;;
    "$VPS3_NAME") ssh $_ssh_opts -p "${VPS3_PORT}" root@${VPS3_IP} "test -e '${path}'" 2>/dev/null ;;
    *) return 1 ;;
  esac
}

# ─── Detectar tipo de panel (HestiaCP vs cPanel/WHM) ──────────────────────────
# VPS1 y VPS2 son cPanel/WHM. VPS3 es HestiaCP.
# Igual verificamos por binarios para no depender de esa convención.
detect_panel_type() {
  local sname="$1"
  if remote_file_exists "$sname" "/usr/local/hestia/bin/v-list-users"; then
    echo "hestia"
  elif remote_file_exists "$sname" "/scripts/removeacct"; then
    echo "cpanel"
  else
    echo "unknown"
  fi
}

# =============================================================================
# PASO 1 — AIRTABLE LOOKUP
# =============================================================================

section() { echo ""; echo -e "${BOLD}── $1 ──────────────────────────────────────────────${NC}"; }

section "1/6  Airtable lookup"

PROJECT_ID="${AIRTABLE_PROJECT_ID_OVERRIDE:-}"   # puede venir de --airtable-project-id
PROJECT_NAME=""
PROJECT_SERVER_AT=""
SUB_IDS=()

if [[ -n "$API_BASE" && -n "$AIRTABLE_PROJECTS_TABLE" ]]; then

  # ── 1a. Buscar Subscriptions por Cpanel_User (campo correcto) ──────────────
  RAW_SUBS="$(curl -sS \
    -H "Authorization: Bearer ${AIRTABLE_TOKEN}" \
    "${API_BASE}/${AIRTABLE_SUBS_TABLE}?filterByFormula=$(urlencode "{Cpanel_User}=\"${CPANEL_USER}\"")\&maxRecords=10")"

  # Extraer IDs de subscriptions y el Project record ID linkeado
  eval "$(python3 - "$RAW_SUBS" <<'PYEOF'
import json, sys, shlex
try:    data = json.loads(sys.argv[1])
except: data = {}
sub_ids = []
project_id_from_sub = ""
for r in data.get("records", []):
    sub_ids.append(r["id"])
    if not project_id_from_sub:
        # "Project" es texto lookup; "Copia de Project" es el linked record array con el rec ID
        for field in ("Copia de Project", "Project"):
            val = r.get("fields", {}).get(field)
            if isinstance(val, list) and val and val[0].startswith("rec"):
                project_id_from_sub = val[0]
                break
print(f'SUB_IDS_FROM_AT=({" ".join(shlex.quote(s) for s in sub_ids)})')
print(f'PROJECT_ID_FROM_SUB={shlex.quote(project_id_from_sub)}')
PYEOF
)"
  for sid in "${SUB_IDS_FROM_AT[@]:-}"; do
    [[ -n "$sid" ]] && SUB_IDS+=("$sid")
  done

  # ── 1b. Resolver PROJECT_ID ────────────────────────────────────────────────
  # Prioridad: --airtable-project-id (pasado desde el panel) > linkeado en sub
  if [[ -z "$PROJECT_ID" && -n "$PROJECT_ID_FROM_SUB" ]]; then
    PROJECT_ID="$PROJECT_ID_FROM_SUB"
  fi

  # ── 1c. Obtener nombre y server del Project record ─────────────────────────
  if [[ -n "$PROJECT_ID" ]]; then
    RAW_PROJECT="$(curl -sS \
      -H "Authorization: Bearer ${AIRTABLE_TOKEN}" \
      "${API_BASE}/${AIRTABLE_PROJECTS_TABLE}/${PROJECT_ID}")"
    PROJECT_NAME="$(python3 -c "
import json,sys
try:
    d=json.loads(sys.argv[1])
    print(d.get('fields',{}).get('Name',''))
except: pass
" "$RAW_PROJECT" 2>/dev/null || true)"
    PROJECT_SERVER_AT="$(python3 -c "
import json,sys
try:
    f=json.loads(sys.argv[1]).get('fields',{})
    print((f.get('SERVER') or f.get('Server','')).strip())
except: pass
" "$RAW_PROJECT" 2>/dev/null || true)"
    ok "Project encontrado: ${PROJECT_NAME} (${PROJECT_ID}) | Server: ${PROJECT_SERVER_AT:-NO SET}"
    ok "Subscriptions encontradas: ${#SUB_IDS[@]}"
  else
    warn "Project NO encontrado en Airtable para Cpanel_User=${CPANEL_USER}"
    warn "Tip: verificá que el proyecto esté en la tabla Subscriptions con ese Cpanel_User"
  fi
else
  warn "Airtable no configurado — se salta lookup"
fi

# =============================================================================
# PASO 2 — DETECTAR SERVIDOR
# =============================================================================

section "2/6  Detectar servidor VPS"

ACTUAL_SERVER=""
PANEL_TYPE=""

if [[ -n "$FORCE_SERVER" ]]; then
  case "$FORCE_SERVER" in
    vps1) ACTUAL_SERVER="$VPS1_NAME" ;;
    vps2) ACTUAL_SERVER="$VPS2_NAME" ;;
    vps3) ACTUAL_SERVER="$VPS3_NAME" ;;
    *)    warn "Servidor desconocido '${FORCE_SERVER}', usando auto-detect" ;;
  esac
fi

if [[ -z "$ACTUAL_SERVER" ]]; then
  # 1. Intentar mapear desde el campo SERVER de Airtable (coincide con los nombres exactos en DB)
  case "$PROJECT_SERVER_AT" in
    "$VPS1_NAME"|"VPS1"|"Hostinger 1") ACTUAL_SERVER="$VPS1_NAME" ;;
    "$VPS2_NAME"|"VPS2"|"Donweb 1")    ACTUAL_SERVER="$VPS2_NAME" ;;
    "$VPS3_NAME"|"VPS3"|"Donweb 2")    ACTUAL_SERVER="$VPS3_NAME" ;;
  esac
fi

if [[ -z "$ACTUAL_SERVER" ]]; then
  # 2. Auto-discovery: buscar la home del usuario en los tres VPS
  #    Orden de búsqueda: según pista de Airtable → fallback completo
  if [[ "$PROJECT_SERVER_AT" == *"Donweb 2"* || "$PROJECT_SERVER_AT" == *"VPS3"* ]]; then
    SEARCH_ORDER=("$VPS3_NAME" "$VPS2_NAME" "$VPS1_NAME")
  elif [[ "$PROJECT_SERVER_AT" == *"Donweb"* || "$PROJECT_SERVER_AT" == *"VPS2"* ]]; then
    SEARCH_ORDER=("$VPS2_NAME" "$VPS1_NAME" "$VPS3_NAME")
  else
    SEARCH_ORDER=("$VPS1_NAME" "$VPS2_NAME" "$VPS3_NAME")
  fi

  for vps in "${SEARCH_ORDER[@]}"; do
    # cPanel: /home/{user} o /var/cpanel/users/{user}
    # HestiaCP: /home/{user}
    if remote_file_exists "$vps" "/home/${CPANEL_USER}" 2>/dev/null || \
       remote_file_exists "$vps" "/var/cpanel/users/${CPANEL_USER}" 2>/dev/null; then
      ACTUAL_SERVER="$vps"
      break
    fi
  done
fi

if [[ -n "$ACTUAL_SERVER" ]]; then
  PANEL_TYPE="$(detect_panel_type "$ACTUAL_SERVER")"
  ok "Servidor: ${ACTUAL_SERVER} | Panel: ${PANEL_TYPE}"
else
  warn "Cuenta '${CPANEL_USER}' no encontrada en ningún VPS — se omite limpieza VPS"
fi

# =============================================================================
# CONFIRMACIÓN INTERACTIVA
# =============================================================================

if [[ "$DRY_RUN" == "false" && "$AUTO_CONFIRM" != "true" ]]; then
  echo ""
  echo -e "  ${RED}${BOLD}⚠  Esta operación es IRREVERSIBLE.${NC}"
  echo "  Se eliminará: VPS account, Cloudinary, DNS, Airtable${ACTUAL_SERVER:+ en ${ACTUAL_SERVER}}"
  read -r -p "  ¿Confirmar eliminación de '${CPANEL_USER}'? [y/N]: " reply
  [[ ! "$reply" =~ ^[Yy]$ ]] && echo "Cancelado." && exit 0
fi

# =============================================================================
# PASO 3 — BACKUP MySQL → Backblaze
# =============================================================================

section "3/6  Backup MySQL → Backblaze"

if [[ "$WITH_BACKUP" == "false" ]]; then
  warn "Backup omitido (--skip-backup)"
elif [[ -z "$ACTUAL_SERVER" ]]; then
  warn "Sin servidor detectado — backup omitido"
elif [[ "$DRY_RUN" == "true" ]]; then
  info "[DRY] mysqldump de '${CPANEL_USER}' en ${ACTUAL_SERVER} → Backblaze"
else
  DUMP_TIMEOUT=1800

  # Crear staging dir
  remote_exec "$ACTUAL_SERVER" "mkdir -p '${BACKUP_STAGING_DIR}'" 2>/dev/null || true

  # Listar DBs del usuario
  DB_LIST="$(remote_exec "$ACTUAL_SERVER" \
    "mysql -N -e 'SHOW DATABASES;' 2>/dev/null | grep -E '^${CPANEL_USER}_|^${CPANEL_USER}\$'" || echo "")"

  if [[ -z "$DB_LIST" ]]; then
    warn "Sin bases de datos para '${CPANEL_USER}' — backup omitido"
    WITH_BACKUP=false
  else
    DUMP_FILE="${BACKUP_STAGING_DIR}/${CPANEL_USER}_$(date +%Y%m%d_%H%M%S).sql.gz"
    REMOTE_DONE="${BACKUP_STAGING_DIR}/.dump-${CPANEL_USER}.done"
    DB_ARGS="$(echo "$DB_LIST" | tr '\n' ' ')"

    info "Databases: $(echo "$DB_LIST" | tr '\n' ' ')"
    info "Iniciando mysqldump en background..."

    remote_exec "$ACTUAL_SERVER" "bash -c '
      nohup bash -c \"mysqldump --single-transaction --routines --triggers \
        --databases ${DB_ARGS} 2>/dev/null | gzip > ${DUMP_FILE}
        echo \\\$? > ${REMOTE_DONE}\" &>/dev/null &
    '" 2>/dev/null || true

    sleep 2
    elapsed=0
    while [[ $elapsed -lt $DUMP_TIMEOUT ]]; do
      remote_exec "$ACTUAL_SERVER" "test -f '${REMOTE_DONE}'" 2>/dev/null && break
      printf "\r  Esperando dump... %ds" "$elapsed"
      sleep 5; elapsed=$((elapsed + 5))
    done
    printf "\r%-60s\n" ""

    DUMP_EXIT="$(remote_exec "$ACTUAL_SERVER" "cat '${REMOTE_DONE}' 2>/dev/null" || echo "1")"
    DUMP_EXIT="${DUMP_EXIT//[^0-9]/}"; DUMP_EXIT="${DUMP_EXIT:-1}"

    if [[ "$DUMP_EXIT" -ne 0 ]]; then
      fail "mysqldump falló (exit ${DUMP_EXIT}) — abortando por seguridad"
      fail "Usá --skip-backup para forzar la eliminación sin backup"
      remote_exec "$ACTUAL_SERVER" "rm -f '${DUMP_FILE}' '${REMOTE_DONE}'" 2>/dev/null || true
      exit 1
    fi

    DUMP_SIZE="$(remote_exec "$ACTUAL_SERVER" "du -sh '${DUMP_FILE}' 2>/dev/null | cut -f1" || echo "?")"
    ok "mysqldump OK: $(basename "$DUMP_FILE") (${DUMP_SIZE})"

    # Upload a Backblaze via WHM transport
    info "Subiendo a Backblaze..."
    DEST_INFO="$(remote_exec "$ACTUAL_SERVER" "
      whmapi1 backup_destination_list --output=json 2>/dev/null \
      | python3 -c \"
import json,sys
data=json.load(sys.stdin)
for d in data.get('data',{}).get('destination_list',[]):
    if str(d.get('disabled','1'))=='0':
        print(d.get('id','')+'|'+d.get('name',''))
        break
\" 2>/dev/null
    " || echo "")"

    TRANSPORT_ID="${DEST_INFO%%|*}"
    TRANSPORT_NAME="${DEST_INFO#*|}"

    if [[ -z "$TRANSPORT_ID" ]]; then
      warn "Sin destino WHM activo — dump queda en ${DUMP_FILE} (subir manualmente)"
      ERRORS=$((ERRORS + 1))
    else
      UPLOAD_OUT="$(remote_exec "$ACTUAL_SERVER" \
        "/scripts/cpbackup_transport_file --transport '${TRANSPORT_ID}' --upload '${DUMP_FILE}' 2>&1" || echo "FAILED")"
      if echo "$UPLOAD_OUT" | grep -qi "failed\|error\|Forbidden\|Exception"; then
        warn "Upload falló — dump queda en ${DUMP_FILE}"
        ERRORS=$((ERRORS + 1))
      else
        ok "Backup subido a Backblaze (${TRANSPORT_NAME})"
        remote_exec "$ACTUAL_SERVER" "rm -f '${DUMP_FILE}' '${REMOTE_DONE}'" 2>/dev/null || true
      fi
    fi
  fi
fi

# =============================================================================
# PASO 4 — ELIMINAR CUENTA VPS
# =============================================================================

section "4/6  Cuenta VPS (${ACTUAL_SERVER:-ninguno})"
write_progress "vps" "running" "Eliminando cuenta en ${ACTUAL_SERVER:-VPS}..."

if [[ -z "$ACTUAL_SERVER" ]]; then
  warn "Sin servidor detectado — omitiendo limpieza VPS"
  write_progress "vps" "done" "Sin servidor detectado — omitido"
elif [[ "$DRY_RUN" == "true" ]]; then
  info "[DRY] Eliminaría cuenta '${CPANEL_USER}' (${PANEL_TYPE}) en ${ACTUAL_SERVER}"
  write_progress "vps" "done" "[DRY] Simulado"
else
  case "$PANEL_TYPE" in
    hestia)
      if remote_exec "$ACTUAL_SERVER" "id '${CPANEL_USER}'" &>/dev/null; then
        if remote_exec "$ACTUAL_SERVER" "v-delete-user '${CPANEL_USER}' yes" 2>&1; then
          ok "Cuenta HestiaCP eliminada"
          write_progress "vps" "done" "Cuenta HestiaCP eliminada"
        else
          warn "v-delete-user falló — intentando limpieza manual..."
          remote_exec "$ACTUAL_SERVER" "userdel -r '${CPANEL_USER}' 2>/dev/null || true"
          remote_exec "$ACTUAL_SERVER" "rm -rf '/home/${CPANEL_USER}' 2>/dev/null || true"
          ok "Cuenta eliminada (fallback manual)"
          write_progress "vps" "done" "Eliminada con fallback manual"
        fi
      else
        warn "Usuario '${CPANEL_USER}' no encontrado en HestiaCP — omitiendo"
        write_progress "vps" "done" "Usuario no encontrado — omitido"
      fi
      ;;
    cpanel)
      REMOVE_OUT="$(remote_exec "$ACTUAL_SERVER" \
        "/scripts/removeacct ${CPANEL_USER} --force" 2>&1)"
      REMOVE_EXIT=$?
      if [[ $REMOVE_EXIT -eq 0 ]]; then
        remote_exec "$ACTUAL_SERVER" \
          "[ -d /home/${CPANEL_USER} ] && rm -rf /home/${CPANEL_USER} || true" 2>/dev/null
        ok "Cuenta cPanel eliminada"
        write_progress "vps" "done" "Cuenta cPanel eliminada"
      else
        fail "removeacct falló: ${REMOVE_OUT}"
        write_progress "vps" "error" "removeacct falló"
        ERRORS=$((ERRORS + 1))
      fi
      ;;
    *)
      warn "Panel desconocido — eliminando archivos manualmente"
      remote_exec "$ACTUAL_SERVER" "userdel -r '${CPANEL_USER}' 2>/dev/null || true"
      remote_exec "$ACTUAL_SERVER" "rm -rf '/home/${CPANEL_USER}' 2>/dev/null || true"
      ok "Archivos eliminados (modo fallback)"
      write_progress "vps" "done" "Archivos eliminados (modo fallback)"
      ;;
  esac
fi

# =============================================================================
# PASO 5 — CLOUDINARY
# =============================================================================

section "5/6  Cloudinary (folder: ${CLOUDINARY_FOLDER}${SUBDOMAIN_FROM_DOMAIN:+ ← de domain})"
write_progress "cloudinary" "running" "Eliminando assets en Cloudinary..."

cld_wait_ratelimit() {
  local resp="$1"
  echo "$resp" | grep -q "Rate Limit Exceeded" || return 1
  local reset_str wait_secs=3600
  reset_str=$(echo "$resp" | grep -o '[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\} [0-9]\{2\}:[0-9]\{2\}:[0-9]\{2\}' | head -1)
  if [[ -n "$reset_str" ]]; then
    local reset_epoch now_epoch
    reset_epoch=$(date -d "${reset_str} UTC" +%s 2>/dev/null || echo 0)
    now_epoch=$(date +%s)
    wait_secs=$(( reset_epoch - now_epoch + 10 ))
    [[ $wait_secs -lt 60 ]] && wait_secs=60
  fi
  warn "Cloudinary rate limit — esperando ${wait_secs}s..."
  sleep "$wait_secs"
  return 0
}

cld_delete_assets() {
  local folder="$1"
  local total_deleted=0
  for rtype in image video raw; do
    local next_cursor=""
    while true; do
      local list_url="${CLOUDINARY_BASE}/resources/${rtype}?prefix=${folder}&max_results=500&type=upload"
      [[ -n "$next_cursor" ]] && list_url="${list_url}&next_cursor=${next_cursor}"
      local list_resp
      while true; do
        list_resp="$(curl -s -u "${CLOUDINARY_API_KEY}:${CLOUDINARY_API_SECRET}" "$list_url")"
        cld_wait_ratelimit "$list_resp" || break
      done
      local ids
      ids="$(echo "$list_resp" | python3 -c "
import json,sys
data=json.load(sys.stdin)
for r in data.get('resources',[]): print(r['public_id'])
" 2>/dev/null || true)"
      [[ -z "$ids" ]] && break

      # Borrar en lotes de 100
      echo "$ids" | split -l 100 - /tmp/cld_batch_
      for bf in /tmp/cld_batch_*; do
        local qs=""
        while IFS= read -r pid; do
          qs="${qs}public_ids[]=$(python3 -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1],safe=''))" "$pid" 2>/dev/null || echo "$pid")&"
        done < "$bf"
        qs="${qs%&}"
        local del_resp
        while true; do
          del_resp="$(curl -s -X DELETE -u "${CLOUDINARY_API_KEY}:${CLOUDINARY_API_SECRET}" \
            "${CLOUDINARY_BASE}/resources/${rtype}/upload?${qs}")"
          cld_wait_ratelimit "$del_resp" || break
        done
        local batch_count
        batch_count="$(echo "$del_resp" | python3 -c "
import json,sys
d=json.load(sys.stdin)
print(len(d.get('deleted',{})))
" 2>/dev/null || echo 0)"
        total_deleted=$((total_deleted + batch_count))
        rm -f "$bf"
      done

      next_cursor="$(echo "$list_resp" | python3 -c "
import json,sys
print(json.load(sys.stdin).get('next_cursor',''))
" 2>/dev/null || true)"
      [[ -z "$next_cursor" ]] && break
    done
  done
  echo "$total_deleted"
}

if [[ -z "$CLOUDINARY_API_KEY" || -z "$CLOUDINARY_API_SECRET" ]]; then
  warn "Cloudinary no configurado — omitiendo"
  write_progress "cloudinary" "done" "No configurado — omitido"
elif [[ "$DRY_RUN" == "true" ]]; then
  info "[DRY] Eliminaría assets y folder '${CLOUDINARY_FOLDER}' en Cloudinary"
  write_progress "cloudinary" "done" "[DRY] Simulado"
else
  DELETED_ASSETS="$(cld_delete_assets "$CLOUDINARY_FOLDER")"
  ok "Assets eliminados: ${DELETED_ASSETS}"
  write_progress "cloudinary" "running" "${DELETED_ASSETS} assets eliminados, borrando folder..."

  # Eliminar el folder
  CLD_FOLDER_RESP="$(curl -s -X DELETE \
    -u "${CLOUDINARY_API_KEY}:${CLOUDINARY_API_SECRET}" \
    "${CLOUDINARY_BASE}/folders/${CLOUDINARY_FOLDER}")"
  if echo "$CLD_FOLDER_RESP" | grep -q '"deleted"'; then
    ok "Folder Cloudinary eliminado"
    write_progress "cloudinary" "done" "${DELETED_ASSETS} assets + folder eliminados"
  else
    CLD_ERR="$(echo "$CLD_FOLDER_RESP" | python3 -c "
import json,sys
try: print(json.load(sys.stdin).get('error',{}).get('message','desconocido'))
except: print('respuesta no JSON')
" 2>/dev/null || echo "error desconocido")"
    warn "Folder Cloudinary no eliminado: ${CLD_ERR}"
    write_progress "cloudinary" "done" "${DELETED_ASSETS} assets eliminados (folder: ${CLD_ERR})"
    # No se cuenta como error crítico — puede estar vacío o no existir
  fi
fi

# =============================================================================
# PASO 6 — DNS HOSTINGER
# =============================================================================

section "6a/6  DNS Hostinger"
write_progress "dns" "running" "Eliminando subdominio DNS..."

SUBDOMAIN="$DNS_SUBDOMAIN"

if [[ -z "$HOSTINGER_TOKEN" ]]; then
  warn "HOSTINGER_TOKEN no configurado — DNS no eliminado"
  write_progress "dns" "done" "Token no configurado — omitido"
elif [[ "$DRY_RUN" == "true" ]]; then
  info "[DRY] DELETE record A '${SUBDOMAIN}.${HOSTINGER_DNS_ZONE}'"
  write_progress "dns" "done" "[DRY] Simulado"
else
  DNS_RESULT="$(curl -sS -w "\n%{http_code}" -X DELETE \
    -H "Authorization: Bearer ${HOSTINGER_TOKEN}" \
    -H "Content-Type: application/json" \
    -d "{\"filters\": [{\"name\": \"${SUBDOMAIN}\", \"type\": \"A\"}]}" \
    "https://developers.hostinger.com/api/dns/v1/zones/${HOSTINGER_DNS_ZONE}")"

  DNS_HTTP="$(echo "$DNS_RESULT" | tail -1)"
  DNS_BODY="$(echo "$DNS_RESULT" | head -n -1)"

  if [[ "$DNS_HTTP" =~ ^2 ]]; then
    ok "DNS eliminado: ${SUBDOMAIN}.${HOSTINGER_DNS_ZONE}"
    write_progress "dns" "done" "${SUBDOMAIN}.${HOSTINGER_DNS_ZONE} eliminado"
  else
    warn "DNS delete HTTP ${DNS_HTTP}: ${DNS_BODY}"
    write_progress "dns" "error" "HTTP ${DNS_HTTP}"
    ERRORS=$((ERRORS + 1))
  fi
fi

# =============================================================================
# PASO 7 — AIRTABLE DELETE
# =============================================================================

section "6b/6  Airtable"
write_progress "airtable" "running" "Eliminando registros en Airtable..."

if [[ "$KEEP_AIRTABLE" == "true" ]]; then
  warn "Airtable preservado (--keep-airtable)"
  write_progress "airtable" "done" "Preservado (--keep-airtable)"
elif [[ -z "$API_BASE" ]]; then
  warn "Airtable no configurado — omitiendo"
  write_progress "airtable" "done" "No configurado — omitido"
elif [[ "$DRY_RUN" == "true" ]]; then
  [[ -n "$PROJECT_ID" ]] && info "[DRY] DELETE Project ${PROJECT_ID}"
  for sid in "${SUB_IDS[@]}"; do
    info "[DRY] DELETE Subscription ${sid}"
  done
  write_progress "airtable" "done" "[DRY] Simulado"
else
  # Eliminar suscripciones primero (FK lógica)
  for sid in "${SUB_IDS[@]}"; do
    DEL_SUB_HTTP="$(curl -sS -o /dev/null -w "%{http_code}" -X DELETE \
      -H "Authorization: Bearer ${AIRTABLE_TOKEN}" \
      "${API_BASE}/${AIRTABLE_SUBS_TABLE}/${sid}")"
    if [[ "$DEL_SUB_HTTP" =~ ^2 ]]; then
      ok "Subscription eliminada: ${sid}"
    else
      warn "Subscription ${sid}: HTTP ${DEL_SUB_HTTP}"
    fi
  done

  # Eliminar Project record
  if [[ -n "$PROJECT_ID" ]]; then
    DEL_PROJ_HTTP="$(curl -sS -o /dev/null -w "%{http_code}" -X DELETE \
      -H "Authorization: Bearer ${AIRTABLE_TOKEN}" \
      "${API_BASE}/${AIRTABLE_PROJECTS_TABLE}/${PROJECT_ID}")"
    if [[ "$DEL_PROJ_HTTP" =~ ^2 ]]; then
      ok "Project eliminado: ${PROJECT_ID} (${PROJECT_NAME})"
      write_progress "airtable" "done" "Project + ${#SUB_IDS[@]} subscription(s) eliminados"
    else
      fail "Project ${PROJECT_ID}: HTTP ${DEL_PROJ_HTTP}"
      write_progress "airtable" "error" "HTTP ${DEL_PROJ_HTTP} al eliminar project"
      ERRORS=$((ERRORS + 1))
    fi
  else
    warn "Sin PROJECT_ID en Airtable — omitiendo"
    write_progress "airtable" "done" "Sin record ID — omitido"
  fi
fi

# =============================================================================
# RESUMEN FINAL
# =============================================================================

echo ""
echo -e "${BOLD}════════════════════════════════════════════${NC}"
if [[ "$DRY_RUN" == "true" ]]; then
  echo -e "  ${YELLOW}DRY RUN completado — no se realizaron cambios${NC}"
elif [[ $ERRORS -eq 0 ]]; then
  echo -e "  ${GREEN}${BOLD}✓ Proyecto '${CPANEL_USER}' eliminado completamente${NC}"
else
  echo -e "  ${YELLOW}⚠ Proyecto '${CPANEL_USER}' eliminado con ${ERRORS} advertencia(s)${NC}"
  echo "    Revisá la salida de arriba para los pasos que fallaron."
fi
echo -e "${BOLD}════════════════════════════════════════════${NC}"
echo ""

# Marcar progreso como completado
if [[ -n "$PROGRESS_FILE" ]]; then
  python3 -c "
import json, os
pf = '$PROGRESS_FILE'
errors = $ERRORS
try:
    with open(pf) as f: data = json.load(f)
except:
    data = {}
data['done'] = True
data['error'] = None if errors == 0 else f'{errors} paso(s) con advertencias'
with open(pf, 'w') as f: json.dump(data, f)
try: os.chmod(pf, 0o644)
except: pass
" 2>/dev/null || true
fi

[[ $ERRORS -gt 0 ]] && exit 1
exit 0
