#!/bin/bash

# Script de déploiement unifié pour GEOSECTOR API
# Version: 4.0 (Janvier 2025)
# Auteur: Pierre (avec l'aide de Claude)
#
# Usage:
#   ./deploy-api.sh          # Déploiement local DEV (code → container geo)
#   ./deploy-api.sh rca      # Livraison RECETTE (container geo → rca-geo)
#   ./deploy-api.sh pra      # Livraison PRODUCTION (rca-geo → pra-geo)

set -euo pipefail

# =====================================
# Configuration générale
# =====================================

# Paramètre optionnel pour l'environnement cible
TARGET_ENV=${1:-dev}

# Configuration SSH
HOST_KEY="/home/pierre/.ssh/id_rsa_mbpi"
HOST_PORT="22"
HOST_USER="root"

# Configuration des serveurs
RCA_HOST="195.154.80.116"  # IN3 - Serveur de recette
PRA_HOST="51.159.7.190"     # IN4 - Serveur de production

# Configuration Incus
INCUS_PROJECT="default"
API_PATH="/var/www/geosector/api"
FINAL_OWNER="nginx"
FINAL_GROUP="nginx"
FINAL_OWNER_LOGS="nobody"
FINAL_GROUP_LOGS="nginx"

# Configuration de sauvegarde
BACKUP_DIR="/home/pierre/samba/back/geosector/api"

# Couleurs pour les messages
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# =====================================
# Fonctions utilitaires
# =====================================

echo_step() {
    echo -e "${GREEN}==>${NC} $1"
}

echo_info() {
    echo -e "${BLUE}Info:${NC} $1"
}

echo_warning() {
    echo -e "${YELLOW}Warning:${NC} $1"
}

echo_error() {
    echo -e "${RED}Error:${NC} $1"
    exit 1
}

# Fonction pour nettoyer les anciens backups
cleanup_old_backups() {
    local prefix=""
    case $TARGET_ENV in
        "dev") prefix="api-dev-" ;;
        "rca") prefix="api-rca-" ;;
        "pra") prefix="api-pra-" ;;
    esac

    echo_info "Cleaning old backups (keeping last 5)..."
    ls -t "${BACKUP_DIR}"/${prefix}*.tar.gz 2>/dev/null | tail -n +6 | xargs -r rm -f && {
        REMAINING_BACKUPS=$(ls "${BACKUP_DIR}"/${prefix}*.tar.gz 2>/dev/null | wc -l)
        echo_info "Kept ${REMAINING_BACKUPS} backup(s) for ${TARGET_ENV}"
    }
}

# =====================================
# Détermination de la configuration selon l'environnement
# =====================================

case $TARGET_ENV in
    "dev")
        echo_step "Configuring for DEV deployment on IN3"
        SOURCE_TYPE="local_code"
        DEST_CONTAINER="dva-geo"
        DEST_HOST="${RCA_HOST}"  # IN3 pour le DEV aussi
        ENV_NAME="DEVELOPMENT"
        ;;
    "rca")
        echo_step "Configuring for RECETTE delivery"
        SOURCE_TYPE="remote_container"
        SOURCE_CONTAINER="dva-geo"
        SOURCE_HOST="${RCA_HOST}"
        DEST_CONTAINER="rca-geo"
        DEST_HOST="${RCA_HOST}"
        ENV_NAME="RECETTE"
        ;;
    "pra")
        echo_step "Configuring for PRODUCTION delivery"
        SOURCE_TYPE="remote_container"
        SOURCE_HOST="${RCA_HOST}"
        SOURCE_CONTAINER="rca-geo"
        DEST_CONTAINER="pra-geo"
        DEST_HOST="${PRA_HOST}"
        ENV_NAME="PRODUCTION"
        ;;
    *)
        echo_error "Unknown environment: $TARGET_ENV. Use 'dev', 'rca' or 'pra'"
        ;;
esac

echo_info "Deployment flow: ${ENV_NAME}"

# =====================================
# Création de l'archive selon la source
# =====================================

# Créer le dossier de backup s'il n'existe pas
if [ ! -d "${BACKUP_DIR}" ]; then
    echo_info "Creating backup directory ${BACKUP_DIR}..."
    mkdir -p "${BACKUP_DIR}" || echo_error "Failed to create backup directory"
fi

# Horodatage format YYYYMMDDHH
TIMESTAMP=$(date +%Y%m%d%H)

# Nom de l'archive selon l'environnement
case $TARGET_ENV in
    "dev")
        ARCHIVE_NAME="api-dev-${TIMESTAMP}.tar.gz"
        ;;
    "rca")
        ARCHIVE_NAME="api-rca-${TIMESTAMP}.tar.gz"
        ;;
    "pra")
        ARCHIVE_NAME="api-pra-${TIMESTAMP}.tar.gz"
        ;;
esac

ARCHIVE_PATH="${BACKUP_DIR}/${ARCHIVE_NAME}"

if [ "$SOURCE_TYPE" = "local_code" ]; then
    # DEV: Créer une archive depuis le code local
    echo_step "Creating archive from local code..."
    
    # Vérification des fichiers requis
    if [ ! -f "src/Config/AppConfig.php" ]; then
        echo_error "Configuration file missing"
    fi
    
    if [ ! -f "composer.json" ] || [ ! -f "composer.lock" ]; then
        echo_error "Composer files missing"
    fi
    
    tar --exclude='.git' \
        --exclude='.gitignore' \
        --exclude='.vscode' \
        --exclude='logs' \
        --exclude='sessions' \
        --exclude='opendata' \
        --exclude='*.template' \
        --exclude='*.sh' \
        --exclude='.env' \
        --exclude='.env_marker' \
        --exclude='*.log' \
        --exclude='.DS_Store' \
        --exclude='README.md' \
        --exclude="*.tar.gz" \
        --exclude='node_modules' \
        --exclude='vendor' \
        --exclude='*.swp' \
        --exclude='*.swo' \
        --exclude='*~' \
        --exclude='docs/*.geojson' \
        --exclude='docs/*.sql' \
        --exclude='docs/*.pdf' \
        --exclude='composer.phar' \
        --exclude='scripts/migration*' \
        --exclude='scripts/php' \
        --exclude='CLAUDE.md' \
        --exclude='TODO-API.md' \
        -czf "${ARCHIVE_PATH}" . 2>/dev/null || echo_error "Failed to create archive"

    echo_info "Archive created: ${ARCHIVE_PATH}"
    echo_info "Archive size: $(du -h "${ARCHIVE_PATH}" | cut -f1)"
    
# Cette section n'est plus utilisée car RCA utilise maintenant remote_container
    
elif [ "$SOURCE_TYPE" = "remote_container" ]; then
    # RCA et PRA: Créer une archive depuis un container distant
    echo_step "Creating archive from remote container ${SOURCE_CONTAINER} on ${SOURCE_HOST}..."
    
    # Créer l'archive sur le serveur source
    ssh -i ${HOST_KEY} -p ${HOST_PORT} ${HOST_USER}@${SOURCE_HOST} "
        incus project switch ${INCUS_PROJECT} &&
        incus exec ${SOURCE_CONTAINER} -- tar \
            --exclude='logs' \
            --exclude='uploads' \
            --exclude='sessions' \
            --exclude='opendata' \
            --exclude='docs/*.geojson' \
            --exclude='docs/*.sql' \
            --exclude='docs/*.pdf' \
            --exclude='composer.phar' \
            --exclude='scripts/migration*' \
            --exclude='scripts/php' \
            --exclude='CLAUDE.md' \
            --exclude='TODO-API.md' \
            --exclude='*.tar.gz' \
            --exclude='vendor' \
            -czf /tmp/${ARCHIVE_NAME} -C ${API_PATH} .
    " || echo_error "Failed to create archive on remote"
    
    # Extraire l'archive du container vers l'hôte
    ssh -i ${HOST_KEY} -p ${HOST_PORT} ${HOST_USER}@${SOURCE_HOST} "
        incus file pull ${SOURCE_CONTAINER}/tmp/${ARCHIVE_NAME} /tmp/${ARCHIVE_NAME} &&
        incus exec ${SOURCE_CONTAINER} -- rm -f /tmp/${ARCHIVE_NAME}
    " || echo_error "Failed to extract archive from remote container"
    
    # Copier l'archive vers la machine locale
    scp -i ${HOST_KEY} -P ${HOST_PORT} ${HOST_USER}@${SOURCE_HOST}:/tmp/${ARCHIVE_NAME} ${ARCHIVE_PATH} || echo_error "Failed to copy archive locally"

    echo_info "Archive saved: ${ARCHIVE_PATH}"
    echo_info "Archive size: $(du -h "${ARCHIVE_PATH}" | cut -f1)"
fi

# Nettoyer les anciens backups
cleanup_old_backups

# =====================================
# Déploiement selon la destination
# =====================================

# Tous les déploiements se font maintenant sur des containers distants
if [ "$DEST_HOST" != "local" ]; then
    # Déploiement sur container distant (DEV, RCA ou PRA)
    echo_step "Deploying to remote container ${DEST_CONTAINER} on ${DEST_HOST}..."
    
    # Créer une sauvegarde sur le serveur de destination
    BACKUP_TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
    REMOTE_BACKUP_DIR="${API_PATH}_backup_${BACKUP_TIMESTAMP}"
    
    echo_info "Creating backup on destination..."
    ssh -i ${HOST_KEY} -p ${HOST_PORT} ${HOST_USER}@${DEST_HOST} "
        incus project switch ${INCUS_PROJECT} &&
        incus exec ${DEST_CONTAINER} -- test -d ${API_PATH} &&
        incus exec ${DEST_CONTAINER} -- cp -r ${API_PATH} ${REMOTE_BACKUP_DIR} &&
        echo 'Backup created: ${REMOTE_BACKUP_DIR}'
    " || echo_warning "No existing installation to backup"
    
    # Transférer l'archive vers le serveur de destination
    echo_info "Transferring archive to ${DEST_HOST}..."
    
    if [ "$SOURCE_TYPE" = "local_code" ]; then
        # Pour DEV: copier depuis local vers IN3
        scp -i ${HOST_KEY} -P ${HOST_PORT} ${ARCHIVE_PATH} ${HOST_USER}@${DEST_HOST}:/tmp/${ARCHIVE_NAME} || echo_error "Failed to copy archive to destination"
    elif [ "$SOURCE_TYPE" = "remote_container" ] && [ "$SOURCE_HOST" = "$DEST_HOST" ]; then
        # Pour RCA: même serveur (IN3), pas de transfert nécessaire, l'archive est déjà là
        echo_info "Archive already on destination server (same host)"
    else
        # Pour PRA: l'archive est déjà sur la machine locale (copiée depuis IN3)
        # On la transfère maintenant vers IN4
        echo_info "Transferring archive from local to IN4..."
        scp -i ${HOST_KEY} -P ${HOST_PORT} ${ARCHIVE_PATH} ${HOST_USER}@${DEST_HOST}:/tmp/${ARCHIVE_NAME} || echo_error "Failed to copy archive to IN4"

        # Nettoyer sur le serveur source IN3
        ssh -i ${HOST_KEY} -p ${HOST_PORT} ${HOST_USER}@${SOURCE_HOST} "rm -f /tmp/${ARCHIVE_NAME}" || echo_warning "Could not clean source server"
    fi
    
    # Déployer sur le container de destination
    echo_info "Extracting on destination container..."

    # Déterminer le nom de l'environnement pour le marqueur
    case $TARGET_ENV in
        "dev") ENV_MARKER="development" ;;
        "rca") ENV_MARKER="recette" ;;
        "pra") ENV_MARKER="production" ;;
    esac

    ssh -i ${HOST_KEY} -p ${HOST_PORT} ${HOST_USER}@${DEST_HOST} "
        set -euo pipefail

        # Pousser l'archive dans le container
        incus project switch ${INCUS_PROJECT} &&
        incus file push /tmp/${ARCHIVE_NAME} ${DEST_CONTAINER}/tmp/${ARCHIVE_NAME} &&

        # Nettoyer sélectivement (préserver logs, uploads et sessions)
        incus exec ${DEST_CONTAINER} -- find ${API_PATH} -mindepth 1 -maxdepth 1 ! -name 'uploads' ! -name 'logs' ! -name 'sessions' -exec rm -rf {} \; 2>/dev/null || true &&

        # Extraire l'archive
        incus exec ${DEST_CONTAINER} -- tar -xzf /tmp/${ARCHIVE_NAME} -C ${API_PATH}/ &&

        # Créer le marqueur d'environnement pour la détection CLI
        incus exec ${DEST_CONTAINER} -- bash -c 'echo \"${ENV_MARKER}\" > ${API_PATH}/.env_marker' &&
        
        # Permissions
        incus exec ${DEST_CONTAINER} -- chown -R ${FINAL_OWNER}:${FINAL_GROUP} ${API_PATH} &&
        incus exec ${DEST_CONTAINER} -- find ${API_PATH} -type d -exec chmod 755 {} \; &&
        incus exec ${DEST_CONTAINER} -- find ${API_PATH} -type f -exec chmod 644 {} \; &&
        
        # Permissions spéciales pour logs (PHP-FPM tourne sous nobody)
        incus exec ${DEST_CONTAINER} -- mkdir -p ${API_PATH}/logs/events &&
        incus exec ${DEST_CONTAINER} -- chown -R ${FINAL_OWNER_LOGS}:${FINAL_GROUP} ${API_PATH}/logs &&
        incus exec ${DEST_CONTAINER} -- find ${API_PATH}/logs -type d -exec chmod 775 {} \; &&
        incus exec ${DEST_CONTAINER} -- find ${API_PATH}/logs -type f -exec chmod 664 {} \; &&
        
        # Permissions spéciales pour uploads
        incus exec ${DEST_CONTAINER} -- mkdir -p ${API_PATH}/uploads &&
        incus exec ${DEST_CONTAINER} -- chown -R ${FINAL_OWNER_LOGS}:${FINAL_GROUP} ${API_PATH}/uploads &&
        incus exec ${DEST_CONTAINER} -- find ${API_PATH}/uploads -type d -exec chmod 750 {} \; &&
        incus exec ${DEST_CONTAINER} -- find ${API_PATH}/uploads -type f -exec chmod 640 {} \; &&

        # Permissions spéciales pour sessions
        incus exec ${DEST_CONTAINER} -- mkdir -p ${API_PATH}/sessions &&
        incus exec ${DEST_CONTAINER} -- chown -R ${FINAL_OWNER_LOGS}:${FINAL_GROUP} ${API_PATH}/sessions &&
        incus exec ${DEST_CONTAINER} -- chmod 700 ${API_PATH}/sessions &&

        # Composer (installation stricte - échec bloquant)
        incus exec ${DEST_CONTAINER} -- bash -c 'cd ${API_PATH} && composer install --no-dev --optimize-autoloader' || { echo 'ERROR: Composer install failed'; exit 1; } &&
        
        # Nettoyage
        incus exec ${DEST_CONTAINER} -- rm -f /tmp/${ARCHIVE_NAME} &&
        rm -f /tmp/${ARCHIVE_NAME}
    " || echo_error "Deployment failed on destination"

    echo_info "Remote backup saved: ${REMOTE_BACKUP_DIR} on ${DEST_CONTAINER}"

    # Nettoyage des anciens backups sur le container distant
    echo_info "Cleaning old backup directories on ${DEST_CONTAINER}..."
    ssh -i ${HOST_KEY} -p ${HOST_PORT} ${HOST_USER}@${DEST_HOST} "
        incus exec ${DEST_CONTAINER} -- bash -c 'rm -rf ${API_PATH}_backup_*'
    " && echo_info "Old backups cleaned" || echo_warning "Could not clean old backups"

    # =====================================
    # Configuration des tâches CRON
    # =====================================

    echo_step "Configuring CRON tasks..."

    ssh -i ${HOST_KEY} -p ${HOST_PORT} ${HOST_USER}@${DEST_HOST} "
        incus exec ${DEST_CONTAINER} -- bash <<'EOFCRON'
            # Sauvegarder les crons existants (hors geosector)
            crontab -l 2>/dev/null | grep -v 'geosector/api/scripts/cron' > /tmp/crontab_backup || true

            # Créer le nouveau crontab avec les tâches CRON pour l'API
            cat /tmp/crontab_backup > /tmp/new_crontab
            cat >> /tmp/new_crontab <<'EOF'

# GEOSECTOR API - Email queue processing (every 5 minutes)
*/5 * * * * /usr/bin/php /var/www/geosector/api/scripts/cron/process_email_queue.php >> /var/www/geosector/api/logs/email_queue.log 2>&1

# GEOSECTOR API - Security data cleanup (daily at 2am)
0 2 * * * /usr/bin/php /var/www/geosector/api/scripts/cron/cleanup_security_data.php >> /var/www/geosector/api/logs/cleanup_security.log 2>&1

# GEOSECTOR API - Event stats aggregation (daily at 1am)
0 1 * * * /usr/bin/php /var/www/geosector/api/scripts/cron/aggregate_event_stats.php >> /var/www/geosector/api/logs/aggregate_stats.log 2>&1
EOF

            # Installer le nouveau crontab
            crontab /tmp/new_crontab

            # Nettoyer
            rm -f /tmp/crontab_backup /tmp/new_crontab

            # Afficher les crons installés
            echo 'CRON tasks installed:'
            crontab -l | grep geosector
EOFCRON
    " && echo_info "CRON tasks configured successfully" || echo_warning "CRON configuration failed"
fi

# L'archive reste dans le dossier de backup, pas de nettoyage nécessaire
echo_info "Archive preserved in backup directory: ${ARCHIVE_PATH}"

# =====================================
# Résumé final
# =====================================

echo_step "Deployment completed successfully!"
echo_info "Environment: ${ENV_NAME}"

if [ "$TARGET_ENV" = "dev" ]; then
    echo_info "Deployed from local code to container ${DEST_CONTAINER} on IN3 (${DEST_HOST})"
elif [ "$TARGET_ENV" = "rca" ]; then
    echo_info "Delivered from ${SOURCE_CONTAINER} to ${DEST_CONTAINER} on ${DEST_HOST}"
elif [ "$TARGET_ENV" = "pra" ]; then
    echo_info "Delivered from ${SOURCE_CONTAINER} on ${SOURCE_HOST} to ${DEST_CONTAINER} on ${DEST_HOST}"
fi

echo_info "Deployment completed at: $(date)"

# Journaliser le déploiement
echo "$(date '+%Y-%m-%d %H:%M:%S') - API deployed to ${ENV_NAME} (${DEST_CONTAINER}) - Archive: ${ARCHIVE_NAME}" >> ~/.geo_deploy_history
