#!/usr/bin/env bash
#
# Backup pre-deploy (bare-metal) — Sucesu V2
# Espelha o estilo de scripts/backup_db.sh e scripts/backup_storage.sh, porem
# usa pg_dump/zip nativos (o ambiente de homolog/producao NAO tem Docker).
# Chamado por ci/deploy.sh ANTES do git reset + migrate.
# Garante um snapshot utilizavel caso o deploy precise ser restaurado.
#
set -euo pipefail
exec 2>&1

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
LOG_FILE="${PROJECT_ROOT}/backup/backup.log"
TIMESTAMP="$(date +%Y%m%dT%H%M%S%z)"

mkdir -p "$(dirname "$LOG_FILE")"

trap 'code=$?; if [ "$code" -ne 0 ]; then echo "[backup.sh] FALHOU (exit $code). backup.log:"; tail -n 40 "$LOG_FILE" 2>/dev/null || true; fi' EXIT

log() {
    local msg="[$(date '+%Y-%m-%d %H:%M:%S %z')] $1"
    echo "$msg"
    {
        flock -x 200
        echo "$msg" >> "$LOG_FILE"
    } 200>"$LOG_FILE"
}

load_env() {
    local env_file="${PROJECT_ROOT}/.env"
    [[ -f "$env_file" ]] || { log "ERROR: .env nao encontrado em ${env_file}"; exit 1; }
    while IFS= read -r line; do
        line="${line%$'\r'}"
        [[ -z "$line" || "$line" == \#* ]] && continue
        case "$line" in
            DB_DATABASE=*) export DB_DATABASE="${line#*=}" ;;
            DB_USERNAME=*) export DB_USERNAME="${line#*=}" ;;
            DB_PASSWORD=*) export DB_PASSWORD="${line#*=}" ;;
            DB_HOST=*)     export DB_HOST="${line#*=}" ;;
            DB_PORT=*)     export DB_PORT="${line#*=}" ;;
        esac
    done < "$env_file"
    DB_HOST="${DB_HOST:-localhost}"
    DB_PORT="${DB_PORT:-5432}"
    for v in DB_DATABASE DB_USERNAME DB_PASSWORD; do
        if [[ -z "${!v:-}" ]]; then
            log "ERROR: ${v} ausente no .env"
            exit 1
        fi
    done
}

backup_db() {
    local out_dir="${PROJECT_ROOT}/backup/db"
    mkdir -p "$out_dir" || { log "ERROR: mkdir falhou para $out_dir"; exit 1; }
    local dump="${out_dir}/backup_${TIMESTAMP}.dump"
    log "INFO: DB dump -> ${dump}"
    PGPASSWORD="$DB_PASSWORD" pg_dump -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USERNAME" \
        -Fc --compress=9 "$DB_DATABASE" > "$dump" 2>"${dump}.err" || {
        log "ERROR: pg_dump falhou"; echo "----- pg_dump stderr -----"; cat "${dump}.err"
        rm -f "$dump" "${dump}.err"; return 1
    }
    rm -f "${dump}.err"
    local size
    size="$(stat -c%s "$dump" 2>/dev/null || echo 0)"
    if [[ "$size" -eq 0 ]]; then
        log "ERROR: dump vazio (0 bytes)"; rm -f "$dump"; return 1
    fi
    if ! pg_restore --list "$dump" >/dev/null 2>&1; then
        log "ERROR: dump invalido (pg_restore --list)"; rm -f "$dump"; return 1
    fi
    log "INFO: DB dump OK (${size} bytes)"
}

backup_storage() {
    local src="${PROJECT_ROOT}/storage/app/public"
    if [[ ! -d "$src" ]]; then
        log "WARN: storage dir ausente (${src}) — pulando backup de storage"
        return 0
    fi
    local out_dir="${PROJECT_ROOT}/backup/storage"
    mkdir -p "$out_dir"
    local zip="${out_dir}/storage_${TIMESTAMP}.zip"
    log "INFO: storage zip -> ${zip}"
    if ! ( cd "$src" && zip -9 -y -T -X -r "$zip" . \
            -x "media_*.zip" -x "legacy-backup/*" -x "legacy-trash/*" >/dev/null 2>&1 ); then
        log "WARN: zip do storage falhou — backup de storage ignorado (deploy continua)"
        rm -f "$zip"
        return 0
    fi
    local size
    size="$(stat -c%s "$zip" 2>/dev/null || echo 0)"
    if [[ "$size" -eq 0 ]]; then
        log "WARN: zip de storage vazio — ignorado"; rm -f "$zip"; return 0
    fi
    log "INFO: storage zip OK (${size} bytes)"
}

main() {
    log "INFO: === pre-deploy backup iniciado ==="
    load_env
    backup_db || { log "ERROR: backup de DB falhou — abortando deploy"; exit 1; }
    backup_storage
    log "INFO: === pre-deploy backup concluido ==="
}

main "$@"
