#!/bin/bash
# ==============================================================================
# Wordly.art - PostgreSQL Backup vers NAS Synology via SSH/rsync
# ==============================================================================
# Sauvegarde la base PostgreSQL et l'archive DR sur le NAS via SSH/rsync.
# Pas de montage CIFS — rsync SSH direct sur /volume1/backups/wordly.
#
# CRON (installé par install-crontab.sh) :
#   0 */6 * * * bash /opt/wordly/scripts/backup-to-nas.sh >> /var/log/wordly-backup.log 2>&1
#
# Usage :
#   ./backup-to-nas.sh              # Backup complet → NAS
#   ./backup-to-nas.sh --full       # Identique (alias explicite)
#   ./backup-to-nas.sh --list       # Lister les archives disponibles sur le NAS
# ==============================================================================

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"

# ==============================================================================
# CHARGER LE .env
# ==============================================================================
ENV_FILE="${PROJECT_ROOT}/.env"
if [ -f "${ENV_FILE}" ]; then
    set -a
    set +u
    source "${ENV_FILE}"
    set -u
    set +a
else
    echo "ERROR: .env introuvable : ${ENV_FILE}" >&2
    exit 1
fi

# ==============================================================================
# CONFIGURATION (depuis .env)
# ==============================================================================

# NAS SSH
NAS_HOST="${NAS_HOST:-192.168.1.146}"
NAS_USER="${NAS_USER:-wordly-backup}"
NAS_PATH="${NAS_PATH:-/volume1/backups/wordly}"
NAS_SSH_PORT="${NAS_SSH_PORT:-22}"
NAS_SSH_KEY="${NAS_SSH_KEY:-/root/.ssh/wordly_nas_key}"

# PostgreSQL
POSTGRES_CONTAINER="${POSTGRES_CONTAINER:-wordly-postgres}"
POSTGRES_USER="${POSTGRES_USER:-translate}"
POSTGRES_DB="${POSTGRES_DB:-translate_db}"
POSTGRES_PASSWORD="${POSTGRES_PASSWORD:?POSTGRES_PASSWORD doit être défini dans .env}"

# Rétention sur le NAS (nombre d'archives à garder)
DAILY_RETENTION=${DAILY_RETENTION:-7}
WEEKLY_RETENTION=${WEEKLY_RETENTION:-4}
MONTHLY_RETENTION=${MONTHLY_RETENTION:-6}

# Telegram
TELEGRAM_BOT_TOKEN="${TELEGRAM_BOT_TOKEN:-}"
TELEGRAM_CHAT_ID="${TELEGRAM_CHAT_ID:-}"

# ==============================================================================
# INTERNALS
# ==============================================================================
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
DAY_OF_WEEK=$(date +"%u")    # 1=Lun, 7=Dim
DAY_OF_MONTH=$(date +"%d")
SNAPSHOT_NAME="wordly_dr_${TIMESTAMP}.tar.gz"
LOCAL_TMP="/tmp/wordly_backup_${TIMESTAMP}"
SSH_CMD="ssh -i ${NAS_SSH_KEY} -p ${NAS_SSH_PORT} -o BatchMode=yes -o ConnectTimeout=10"
RSYNC_CMD="rsync -az -e 'ssh -i ${NAS_SSH_KEY} -p ${NAS_SSH_PORT} -o BatchMode=yes -o ConnectTimeout=10'"

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
LOG_PREFIX="[Backup ${TIMESTAMP}]"

log()         { echo "${LOG_PREFIX} $1" >&2; }
log_success() { echo -e "${LOG_PREFIX} ${GREEN}✅ $1${NC}" >&2; }
log_error()   { echo -e "${LOG_PREFIX} ${RED}❌ ERROR: $1${NC}" >&2; }
log_warning() { echo -e "${LOG_PREFIX} ${YELLOW}⚠️  $1${NC}" >&2; }

# ==============================================================================
# TELEGRAM
# ==============================================================================
send_telegram() {
    local message="$1"
    if [ -n "${TELEGRAM_BOT_TOKEN}" ] && [ -n "${TELEGRAM_CHAT_ID}" ]; then
        curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
            -d "chat_id=${TELEGRAM_CHAT_ID}" \
            -d "text=${message}" \
            -d "parse_mode=Markdown" \
            >/dev/null 2>&1 || true
    fi
}

# ==============================================================================
# PRÉREQUIS
# ==============================================================================
check_prerequisites() {
    log "Vérification des prérequis..."

    # Clé SSH
    if [ ! -f "${NAS_SSH_KEY}" ]; then
        log_error "Clé SSH introuvable : ${NAS_SSH_KEY}"
        log_error "Lancez d'abord : sudo bash scripts/setup-nas.sh"
        exit 1
    fi

    # Connectivité SSH vers le NAS
    if ! ${SSH_CMD} "${NAS_USER}@${NAS_HOST}" "echo OK" >/dev/null 2>&1; then
        log_error "Impossible de se connecter au NAS ${NAS_HOST} via SSH."
        log_error "Vérifiez : ssh -i ${NAS_SSH_KEY} ${NAS_USER}@${NAS_HOST}"
        send_telegram "🚨 *Wordly Backup ÉCHOUÉ*
NAS inaccessible : ${NAS_HOST}
Date : $(date '+%Y-%m-%d %H:%M:%S')"
        exit 1
    fi
    log_success "NAS SSH : OK"

    # Docker + container PostgreSQL
    if ! docker ps --format '{{.Names}}' 2>/dev/null | grep -q "^${POSTGRES_CONTAINER}$"; then
        log_error "Container PostgreSQL '${POSTGRES_CONTAINER}' n'est pas en cours d'exécution !"
        send_telegram "🚨 *Wordly Backup ÉCHOUÉ*
PostgreSQL container non trouvé
Date : $(date '+%Y-%m-%d %H:%M:%S')"
        exit 1
    fi
    log_success "PostgreSQL container : OK"
}

# ==============================================================================
# BACKUP POSTGRESQL
# ==============================================================================
backup_postgres() {
    log "Dump PostgreSQL de '${POSTGRES_DB}'..."
    mkdir -p "${LOCAL_TMP}"

    local dump_file="${LOCAL_TMP}/db_${TIMESTAMP}.dump.gz"

    if ! docker exec \
        -e PGPASSWORD="${POSTGRES_PASSWORD}" \
        "${POSTGRES_CONTAINER}" \
        pg_dump \
            -U "${POSTGRES_USER}" \
            -d "${POSTGRES_DB}" \
            --format=custom \
            --no-owner \
            --no-acl \
        2>/dev/null | gzip > "${dump_file}"; then
        log_error "pg_dump a échoué !"
        send_telegram "🚨 *Wordly Backup ÉCHOUÉ*
pg_dump error sur ${POSTGRES_DB}
Date : $(date '+%Y-%m-%d %H:%M:%S')"
        rm -rf "${LOCAL_TMP}"
        exit 1
    fi

    # Vérification taille
    local size_bytes
    size_bytes=$(stat -c %s "${dump_file}" 2>/dev/null || stat -f %z "${dump_file}")
    local min_bytes=1024  # 1KB minimum (safe for new/small databases)

    if [ "${size_bytes}" -lt "${min_bytes}" ]; then
        log_error "Dump trop petit ($(numfmt --to=iec ${size_bytes})) — base de données vide ?"
        send_telegram "🚨 *Wordly Backup ÉCHOUÉ*
Dump PostgreSQL trop petit : $(numfmt --to=iec ${size_bytes})
Date : $(date '+%Y-%m-%d %H:%M:%S')"
        rm -rf "${LOCAL_TMP}"
        exit 1
    fi

    log_success "Dump PostgreSQL : $(numfmt --to=iec ${size_bytes})"
    echo "${dump_file}"
}

# ==============================================================================
# CRÉER L'ARCHIVE DR (dump + .env + docker-compose + configs)
# ==============================================================================
create_dr_archive() {
    local dump_file="$1"
    log "Construction de l'archive DR..."

    # Copier les fichiers de config
    [ -f "${PROJECT_ROOT}/.env" ]              && cp "${PROJECT_ROOT}/.env" "${LOCAL_TMP}/.env.production"
    [ -f "${PROJECT_ROOT}/docker-compose.yml" ] && cp "${PROJECT_ROOT}/docker-compose.yml" "${LOCAL_TMP}/"
    [ -d "${PROJECT_ROOT}/docker" ]             && cp -r "${PROJECT_ROOT}/docker" "${LOCAL_TMP}/"

    # Compresser
    local archive_path="/tmp/${SNAPSHOT_NAME}"
    tar -czf "${archive_path}" -C "${LOCAL_TMP}" .
    rm -rf "${LOCAL_TMP}"

    # Vérification intégrité
    if ! gzip -t "${archive_path}" 2>/dev/null; then
        log_error "Archive DR corrompue !"
        rm -f "${archive_path}"
        exit 1
    fi

    local size
    size=$(du -h "${archive_path}" | cut -f1)
    log_success "Archive DR créée : ${SNAPSHOT_NAME} (${size})"
    echo "${archive_path}|${size}"
}

# ==============================================================================
# ENVOYER SUR LE NAS VIA SCP/rsync SSH
# ==============================================================================
push_to_nas() {
    local archive_path="$1"
    local size="$2"

    log "Transfert vers le NAS via rsync SSH..."
    log "  Source : ${archive_path}"
    log "  Dest   : ${NAS_USER}@${NAS_HOST}:${NAS_PATH}/snapshots/${SNAPSHOT_NAME}"

    # Dossier quotidien/hebdo/mensuel sur le NAS
    local nas_dest="${NAS_PATH}/snapshots"

    # Transfer principal
    if ! rsync -az \
        -e "ssh -i ${NAS_SSH_KEY} -p ${NAS_SSH_PORT} -o BatchMode=yes -o ConnectTimeout=30" \
        "${archive_path}" \
        "${NAS_USER}@${NAS_HOST}:${nas_dest}/${SNAPSHOT_NAME}"; then
        log_error "rsync vers le NAS a échoué !"
        send_telegram "🚨 *Wordly Backup ÉCHOUÉ*
rsync SSH vers ${NAS_HOST} a échoué
Fichier local conservé : ${archive_path}
Date : $(date '+%Y-%m-%d %H:%M:%S')"
        # Garder le fichier local comme fallback
        mkdir -p "${PROJECT_ROOT}/backups/emergency"
        mv "${archive_path}" "${PROJECT_ROOT}/backups/emergency/${SNAPSHOT_NAME}"
        log_warning "Archive conservée localement : ${PROJECT_ROOT}/backups/emergency/${SNAPSHOT_NAME}"
        exit 1
    fi

    log_success "Archive transférée sur le NAS : ${nas_dest}/${SNAPSHOT_NAME}"

    # Copie hebdomadaire (dimanche)
    if [ "${DAY_OF_WEEK}" = "7" ]; then
        ${SSH_CMD} "${NAS_USER}@${NAS_HOST}" \
            "cp ${nas_dest}/${SNAPSHOT_NAME} ${NAS_PATH}/snapshots/weekly_${SNAPSHOT_NAME}" 2>/dev/null || true
        log "Archive hebdomadaire copiée."
    fi

    # Copie mensuelle (1er du mois)
    if [ "${DAY_OF_MONTH}" = "01" ]; then
        ${SSH_CMD} "${NAS_USER}@${NAS_HOST}" \
            "cp ${nas_dest}/${SNAPSHOT_NAME} ${NAS_PATH}/snapshots/monthly_${SNAPSHOT_NAME}" 2>/dev/null || true
        log "Archive mensuelle copiée."
    fi

    # Nettoyage local
    rm -f "${archive_path}"
}

# ==============================================================================
# ROTATION DES ARCHIVES SUR LE NAS
# ==============================================================================
cleanup_nas() {
    log "Rotation des archives sur le NAS (conservation : ${DAILY_RETENTION} jours)..."

    # Supprimer les archives wordly_dr_* plus vieilles que DAILY_RETENTION
    ${SSH_CMD} "${NAS_USER}@${NAS_HOST}" \
        "find ${NAS_PATH}/snapshots -name 'wordly_dr_*.tar.gz' -mtime +${DAILY_RETENTION} -delete 2>/dev/null; \
         find ${NAS_PATH}/snapshots -name 'weekly_*.tar.gz' | sort -r | tail -n +$((WEEKLY_RETENTION + 1)) | xargs rm -f 2>/dev/null; \
         find ${NAS_PATH}/snapshots -name 'monthly_*.tar.gz' | sort -r | tail -n +$((MONTHLY_RETENTION + 1)) | xargs rm -f 2>/dev/null; \
         echo OK" | grep -q "OK"

    log_success "Rotation des archives OK"
}

# ==============================================================================
# SYNCHRONISER LES SCRIPTS SUR LE NAS (pour restauration depuis .98)
# ==============================================================================
sync_scripts() {
    rsync -az \
        -e "ssh -i ${NAS_SSH_KEY} -p ${NAS_SSH_PORT} -o BatchMode=yes" \
        --exclude="__pycache__" \
        --exclude="*.pyc" \
        "${SCRIPT_DIR}/" \
        "${NAS_USER}@${NAS_HOST}:${NAS_PATH}/scripts/" 2>/dev/null || true
}

# ==============================================================================
# LISTER LES ARCHIVES DISPONIBLES
# ==============================================================================
list_archives() {
    log "Archives disponibles sur le NAS :"
    ${SSH_CMD} "${NAS_USER}@${NAS_HOST}" \
        "ls -lht ${NAS_PATH}/snapshots/wordly_dr_*.tar.gz 2>/dev/null || echo '(aucune archive)'"
}

# ==============================================================================
# MAIN
# ==============================================================================
main() {
    case "${1:-}" in
        --list)
            ENV_FILE="${PROJECT_ROOT}/.env"
            [ -f "${ENV_FILE}" ] && { set -a; source "${ENV_FILE}"; set +a; }
            list_archives
            exit 0
            ;;
        --full|*)
            ;;
    esac

    echo ""
    echo "================================================================="
    echo "  Wordly.art — Backup → NAS Synology 192.168.1.146"
    echo "  DB  : ${POSTGRES_DB}"
    echo "  NAS : ${NAS_USER}@${NAS_HOST}:${NAS_PATH}"
    echo "  $(date '+%Y-%m-%d %H:%M:%S')"
    echo "================================================================="
    echo ""

    check_prerequisites

    # 1. Dump PostgreSQL
    local dump_file
    dump_file=$(backup_postgres)

    # 2. Créer l'archive DR
    local archive_info
    archive_info=$(create_dr_archive "${dump_file}")
    local archive_path="${archive_info%%|*}"
    local archive_size="${archive_info##*|}"

    # 3. Envoyer sur le NAS via rsync SSH
    push_to_nas "${archive_path}" "${archive_size}"

    # 4. Rotation
    cleanup_nas

    # 5. Sync scripts
    sync_scripts

    # 6. Notification Telegram
    send_telegram "✅ *Wordly.art Backup OK*
Archive : \`${SNAPSHOT_NAME}\`
Taille  : ${archive_size}
NAS     : \`${NAS_PATH}/snapshots/\`
Date    : $(date '+%Y-%m-%d %H:%M:%S')"

    echo ""
    log_success "================================================================="
    log_success "Backup complet terminé !"
    log_success "  Archive : ${NAS_PATH}/snapshots/${SNAPSHOT_NAME}"
    log_success "  Lister  : bash scripts/backup-to-nas.sh --list"
    log_success "================================================================="
    echo ""
}

main "$@"
