#!/bin/bash
# E-Ticket - Script d'export pour migration de serveur
# Genere un bundle complet et autonome pour migrer l'application sur un autre serveur.
#
# Le bundle contient:
#   - dump de la base PostgreSQL                       (db.sql.gz)
#   - uploads Vich/Flysystem (events, billets, logos)  (public_uploads.tar.gz)
#   - etat applicatif var/                             (var_state.tar.gz)
#       payouts/, billets/, invoices/, unsubscribed.json
#   - configuration runtime sensible                   (env.local, cert/)
#   - manifest avec checksums SHA-256                  (manifest.txt)
#
# Le tout est ensuite empaquete dans une archive .tar.gz transferable par scp/rsync.
#
# Usage:
#   ./backup.sh [DOSSIER_DESTINATION]
#
# Variables d'environnement supportees:
#   COMPOSE_FILE  : fichier docker-compose a utiliser  (defaut: docker-compose-prod.yml)
#   DB_SERVICE    : service Docker de la base          (defaut: db-master)
#   DB_USER       : utilisateur PostgreSQL             (defaut: e-ticket)
#   DB_NAME       : base de donnees a exporter         (defaut: e-ticket)
#   SKIP_SECRETS  : '1' pour exclure .env.local + cert (defaut: inclus)

set -euo pipefail

# --- Configuration ---
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DEST_DIR="${1:-${SCRIPT_DIR}/var/migration}"
COMPOSE_FILE="${COMPOSE_FILE:-${SCRIPT_DIR}/docker-compose-prod.yml}"
DB_SERVICE="${DB_SERVICE:-db-master}"
DB_USER="${DB_USER:-e-ticket}"
DB_NAME="${DB_NAME:-e-ticket}"
SKIP_SECRETS="${SKIP_SECRETS:-0}"

DATE="$(date +%Y%m%d_%H%M%S)"
BUNDLE_NAME="e_ticket_migration_${DATE}"
WORK_DIR="${DEST_DIR}/${BUNDLE_NAME}"
BUNDLE_FILE="${DEST_DIR}/${BUNDLE_NAME}.tar.gz"

log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"
}

err() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERREUR: $*" >&2
}

cleanup() {
    if [ -d "${WORK_DIR}" ]; then
        rm -rf "${WORK_DIR}"
    fi
}

# Cleanup du WORK_DIR meme en cas d'erreur (le BUNDLE_FILE final reste)
trap cleanup EXIT

# --- Verifications prealables ---
if [ ! -f "${COMPOSE_FILE}" ]; then
    err "Fichier docker-compose introuvable: ${COMPOSE_FILE}"
    exit 1
fi

if ! docker compose -f "${COMPOSE_FILE}" ps --services --status running 2>/dev/null | grep -qx "${DB_SERVICE}"; then
    err "Le service '${DB_SERVICE}' n'est pas demarre"
    err "Demarrer la stack avec: make start_prod"
    exit 1
fi

mkdir -p "${WORK_DIR}"

log "=== Export de migration E-Ticket ==="
log "Bundle: ${BUNDLE_NAME}"
log "Destination: ${DEST_DIR}"

# --- 1. Dump base de donnees ---
log "[1/5] Dump PostgreSQL '${DB_NAME}' depuis ${DB_SERVICE}..."
if ! docker compose -f "${COMPOSE_FILE}" exec -T "${DB_SERVICE}" \
        pg_dump -U "${DB_USER}" -d "${DB_NAME}" \
                --clean --if-exists --no-owner --no-privileges --quote-all-identifiers \
        | gzip > "${WORK_DIR}/db.sql.gz"; then
    err "Echec du dump PostgreSQL"
    exit 1
fi
if [ ! -s "${WORK_DIR}/db.sql.gz" ]; then
    err "Le dump PostgreSQL est vide"
    exit 1
fi
log "    OK ($(du -h "${WORK_DIR}/db.sql.gz" | cut -f1))"

# --- 2. Uploads publics (events, billets, logos) ---
log "[2/5] Archivage public/uploads (events, billets, logos)..."
if [ -d "${SCRIPT_DIR}/public/uploads" ]; then
    tar -czf "${WORK_DIR}/public_uploads.tar.gz" -C "${SCRIPT_DIR}/public" uploads
    log "    OK ($(du -h "${WORK_DIR}/public_uploads.tar.gz" | cut -f1))"
else
    err "public/uploads introuvable"
    exit 1
fi

# --- 3. Etat applicatif var/ (PDFs generes, desinscrits...) ---
log "[3/5] Archivage etat applicatif var/ (payouts, billets, invoices, unsubscribed.json)..."
VAR_ITEMS=()
for item in payouts billets invoices unsubscribed.json; do
    if [ -e "${SCRIPT_DIR}/var/${item}" ]; then
        VAR_ITEMS+=("${item}")
    fi
done
if [ ${#VAR_ITEMS[@]} -gt 0 ]; then
    tar -czf "${WORK_DIR}/var_state.tar.gz" -C "${SCRIPT_DIR}/var" "${VAR_ITEMS[@]}"
    log "    OK - elements inclus: ${VAR_ITEMS[*]} ($(du -h "${WORK_DIR}/var_state.tar.gz" | cut -f1))"
else
    log "    Aucun element a archiver dans var/ (saut)"
fi

# --- 4. Configuration runtime sensible ---
if [ "${SKIP_SECRETS}" = "1" ]; then
    log "[4/5] Secrets exclus (SKIP_SECRETS=1)"
    log "    ATTENTION: vous devrez deployer .env.local et config/cert/ manuellement sur le nouveau serveur"
else
    log "[4/5] Archivage configuration sensible (.env.local + config/cert/)..."
    SECRET_ITEMS=()
    if [ -f "${SCRIPT_DIR}/.env.local" ]; then
        cp -p "${SCRIPT_DIR}/.env.local" "${WORK_DIR}/env.local"
        chmod 600 "${WORK_DIR}/env.local"
        SECRET_ITEMS+=(".env.local")
    fi
    if [ -d "${SCRIPT_DIR}/config/cert" ]; then
        mkdir -p "${WORK_DIR}/cert"
        cp -rp "${SCRIPT_DIR}/config/cert/." "${WORK_DIR}/cert/"
        chmod -R go-rwx "${WORK_DIR}/cert"
        SECRET_ITEMS+=("config/cert/")
    fi
    if [ ${#SECRET_ITEMS[@]} -gt 0 ]; then
        log "    OK - elements inclus: ${SECRET_ITEMS[*]}"
    else
        log "    Aucun secret trouve a archiver (saut)"
    fi
fi

# --- 5. Manifest avec checksums et metadata ---
log "[5/5] Generation du manifest..."
{
    echo "# E-Ticket migration bundle"
    echo "bundle_name: ${BUNDLE_NAME}"
    echo "created_at: $(date --iso-8601=seconds)"
    echo "source_host: $(hostname)"
    echo "git_commit: $(git -C "${SCRIPT_DIR}" rev-parse HEAD 2>/dev/null || echo 'unknown')"
    echo "git_branch: $(git -C "${SCRIPT_DIR}" rev-parse --abbrev-ref HEAD 2>/dev/null || echo 'unknown')"
    echo "db_name: ${DB_NAME}"
    echo "db_user: ${DB_USER}"
    echo "skip_secrets: ${SKIP_SECRETS}"
    echo
    echo "# SHA-256 checksums"
    (cd "${WORK_DIR}" && find . -type f ! -name 'manifest.txt' -print0 | sort -z | xargs -0 sha256sum)
} > "${WORK_DIR}/manifest.txt"
log "    OK"

# --- Empaquetage final ---
log "Empaquetage du bundle dans ${BUNDLE_FILE}..."
tar -czf "${BUNDLE_FILE}" -C "${DEST_DIR}" "${BUNDLE_NAME}"
BUNDLE_SIZE="$(du -h "${BUNDLE_FILE}" | cut -f1)"
BUNDLE_SHA="$(sha256sum "${BUNDLE_FILE}" | cut -d' ' -f1)"

log "=== Export termine ==="
log "Bundle    : ${BUNDLE_FILE}"
log "Taille    : ${BUNDLE_SIZE}"
log "SHA-256   : ${BUNDLE_SHA}"
log
log "Pour transferer vers le nouveau serveur:"
log "  scp '${BUNDLE_FILE}' user@nouveau-serveur:/var/www/e-ticket/"
log "Puis sur le nouveau serveur:"
log "  ./restore.sh '${BUNDLE_NAME}.tar.gz'"
