#!/bin/bash

# Migration de Magento depuis un serveur existant avec configuration Varnish
# ========================================================================

# Chargement de la configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/00_config.sh"

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

# Fonction pour afficher un message de statut
status_message() {
    local status=$1
    local message=$2
    
    if [ "$status" = "OK" ]; then
        echo -e "[${GREEN}OK${NC}] $message"
    elif [ "$status" = "WARNING" ]; then
        echo -e "[${YELLOW}WARNING${NC}] $message"
    elif [ "$status" = "ERROR" ]; then
        echo -e "[${RED}ERROR${NC}] $message"
    elif [ "$status" = "INFO" ]; then
        echo -e "[${BLUE}INFO${NC}] $message"
    else
        echo "$message"
    fi
}

# Fonction pour vérifier les droits root
check_root() {
    if [ "$(id -u)" -ne 0 ]; then
        status_message "ERROR" "Ce script doit être exécuté en tant que root"
        exit 1
    fi
}

# Vérification des droits root
check_root

# Création d'un timestamp pour les sauvegardes
TIMESTAMP=$(date +%Y%m%d%H%M%S)
ARCHIVE_NAME="magento_source_${TIMESTAMP}.tar.gz"
# Répertoire temporaire sur le serveur de destination
TEMP_ARCHIVE="/home/${ARCHIVE_NAME}"
BACKUP_ARCHIVE="${BACKUP_DIR}/${ARCHIVE_NAME}"

# Fonction pour vérifier les prérequis
check_prerequisites() {
    status_message "INFO" "Vérification des prérequis..."
    
    # Vérification de la connexion SSH
    status_message "INFO" "Vérification de la connexion SSH au serveur source..."
    if command -v sshpass &> /dev/null; then
        sshpass -p "${SSH_PASSWORD}" ssh -o StrictHostKeyChecking=no ${SOURCE_USER}@${SOURCE_SERVER} "echo 'Connexion SSH réussie'" > /dev/null 2>&1
    else
        ssh -o StrictHostKeyChecking=no ${SOURCE_USER}@${SOURCE_SERVER} "echo 'Connexion SSH réussie'" > /dev/null 2>&1
    fi
    
    if [ $? -ne 0 ]; then
        status_message "ERROR" "Impossible de se connecter au serveur source via SSH."
        exit 1
    fi
    
    # Vérification de l'existence du répertoire Magento sur le serveur source
    status_message "INFO" "Vérification de l'existence du répertoire Magento sur le serveur source..."
    if command -v sshpass &> /dev/null; then
        sshpass -p "${SSH_PASSWORD}" ssh ${SOURCE_USER}@${SOURCE_SERVER} "test -d ${SOURCE_MAGENTO_PATH}"
    else
        ssh ${SOURCE_USER}@${SOURCE_SERVER} "test -d ${SOURCE_MAGENTO_PATH}"
    fi
    
    if [ $? -ne 0 ]; then
        status_message "ERROR" "Le répertoire Magento n'existe pas sur le serveur source: ${SOURCE_MAGENTO_PATH}"
        exit 1
    fi
    
    # Vérification de l'existence du répertoire de destination
    status_message "INFO" "Vérification de l'existence du répertoire de destination..."
    if [ ! -d "$DEST_MAGENTO_PATH" ]; then
        status_message "INFO" "Création du répertoire de destination: $DEST_MAGENTO_PATH"
        mkdir -p $DEST_MAGENTO_PATH
        chown $DEST_USER:$DEST_GROUP $DEST_MAGENTO_PATH
    fi
    
    # Vérification de l'espace disque disponible
    status_message "INFO" "Vérification de l'espace disque disponible..."
    REQUIRED_SPACE=10000000  # 10 Go en Ko (réduit car on utilise /home)
    AVAILABLE_SPACE=$(df -k /home | tail -1 | awk '{print $4}')
    
    if [ $AVAILABLE_SPACE -lt $REQUIRED_SPACE ]; then
        status_message "ERROR" "Espace disque insuffisant. Disponible: $(($AVAILABLE_SPACE / 1024)) Mo, Requis: $(($REQUIRED_SPACE / 1024)) Mo"
        exit 1
    fi
    
    # Création du répertoire de sauvegarde si nécessaire
    if [ ! -d "$BACKUP_DIR" ]; then
        mkdir -p $BACKUP_DIR
        chown $DEST_USER:$DEST_GROUP $BACKUP_DIR
    fi
    
    status_message "OK" "Prérequis vérifiés avec succès."
}

# Fonction pour nettoyer le cache Magento et optimiser pour la production
clean_magento_cache() {
    status_message "INFO" "Nettoyage du cache Magento et optimisation..."
    
    # Suppression des répertoires de cache
    rm -rf $DEST_MAGENTO_PATH/var/cache/*
    rm -rf $DEST_MAGENTO_PATH/var/page_cache/*
    rm -rf $DEST_MAGENTO_PATH/generated/code/*
    rm -rf $DEST_MAGENTO_PATH/generated/metadata/*
    rm -rf $DEST_MAGENTO_PATH/pub/static/_cache/*
    
    # Vider le cache Redis
    status_message "INFO" "Vidage des bases de données Redis..."
    redis-cli -h 127.0.0.1 -p 6379 FLUSHDB
    redis-cli -h 127.0.0.1 -p 6379 -n 1 FLUSHDB
    redis-cli -h 127.0.0.1 -p 6379 -n 2 FLUSHDB
    redis-cli -h 127.0.0.1 -p 6379 -n 3 FLUSHDB
    
    # Passage en mode maintenance pendant les opérations
    status_message "INFO" "Activation du mode maintenance..."
    su - $DEST_USER -c "cd $DEST_MAGENTO_PATH && php bin/magento maintenance:enable"
    
    # Exécution des commandes Magento en tant qu'utilisateur Magento
    status_message "INFO" "Mise à jour de la base de données et compilation du code..."
    su - $DEST_USER -c "cd $DEST_MAGENTO_PATH && php bin/magento setup:upgrade --keep-generated"
    su - $DEST_USER -c "cd $DEST_MAGENTO_PATH && php bin/magento setup:di:compile"
    
    # Déploiement des fichiers statiques pour toutes les locales
    status_message "INFO" "Déploiement des fichiers statiques (peut prendre plusieurs minutes)..."
    su - $DEST_USER -c "cd $DEST_MAGENTO_PATH && php bin/magento setup:static-content:deploy fr_FR en_US -f"
    
    # Réindexation complète
    status_message "INFO" "Réindexation complète du catalogue..."
    su - $DEST_USER -c "cd $DEST_MAGENTO_PATH && php bin/magento indexer:reindex"
    
    # Nettoyage final des caches
    status_message "INFO" "Nettoyage final des caches..."
    su - $DEST_USER -c "cd $DEST_MAGENTO_PATH && php bin/magento cache:clean"
    su - $DEST_USER -c "cd $DEST_MAGENTO_PATH && php bin/magento cache:flush"
    
    # Réindexation spécifique pour Elasticsearch
    status_message "INFO" "Réindexation pour Elasticsearch..."
    su - $DEST_USER -c "cd $DEST_MAGENTO_PATH && php bin/magento indexer:reindex catalogsearch_fulltext"
    
    # Désactivation du mode maintenance
    status_message "INFO" "Désactivation du mode maintenance..."
    su - $DEST_USER -c "cd $DEST_MAGENTO_PATH && php bin/magento maintenance:disable"
    
    status_message "OK" "Optimisation terminée avec succès."
}

# Fonction pour vérifier les archives existantes
check_existing_archives() {
    status_message "INFO" "Recherche d'archives existantes sur le serveur source..."
    
    # Création du répertoire temporaire sur le serveur source s'il n'existe pas
    if command -v sshpass &> /dev/null; then
        sshpass -p "${SSH_PASSWORD}" ssh ${SOURCE_USER}@${SOURCE_SERVER} "mkdir -p ${TEMP_DIR}"
        # Liste des archives existantes
        ARCHIVES=$(sshpass -p "${SSH_PASSWORD}" ssh ${SOURCE_USER}@${SOURCE_SERVER} "find ${TEMP_DIR} -name 'magento_source_*.tar.gz' -type f -printf '%T@ %s %p\n' | sort -nr")
    else
        ssh ${SOURCE_USER}@${SOURCE_SERVER} "mkdir -p ${TEMP_DIR}"
        # Liste des archives existantes
        ARCHIVES=$(ssh ${SOURCE_USER}@${SOURCE_SERVER} "find ${TEMP_DIR} -name 'magento_source_*.tar.gz' -type f -printf '%T@ %s %p\n' | sort -nr")
    fi
    
    if [ -z "$ARCHIVES" ]; then
        status_message "INFO" "Aucune archive existante trouvée."
        return 1
    fi
    
    status_message "INFO" "Archives existantes trouvées:"
    echo "$ARCHIVES" | while read line; do
        TIMESTAMP=$(echo $line | awk '{print $1}')
        SIZE=$(echo $line | awk '{print $2}')
        PATH=$(echo $line | awk '{print $3}')
        HUMAN_DATE=$(date -d @${TIMESTAMP%.*} "+%Y-%m-%d %H:%M:%S")
        HUMAN_SIZE=$(echo $SIZE | awk '{ suffix="KMGT"; for(i=1; $1>1024 && i < length(suffix); i++) $1/=1024; print int($1) substr(suffix, i, 1) "o" }')
        
        echo "- $(basename $PATH) (Taille: $HUMAN_SIZE, Date: $HUMAN_DATE)"
    done
    
    read -p "Voulez-vous utiliser une archive existante? (o/n): " USE_EXISTING
    if [[ "$USE_EXISTING" =~ ^[Oo]$ ]]; then
        echo "$ARCHIVES" | nl
        read -p "Entrez le numéro de l'archive à utiliser: " ARCHIVE_NUM
        
        SELECTED_ARCHIVE=$(echo "$ARCHIVES" | sed -n "${ARCHIVE_NUM}p" | awk '{print $3}')
        if [ -z "$SELECTED_ARCHIVE" ]; then
            status_message "ERROR" "Sélection invalide."
            return 1
        fi
        
        ARCHIVE_NAME=$(basename $SELECTED_ARCHIVE)
        status_message "INFO" "Archive sélectionnée: $ARCHIVE_NAME"
        return 0
    else
        status_message "INFO" "Création d'une nouvelle archive..."
        return 1
    fi
}

# Fonction pour créer une archive des fichiers Magento sur le serveur source
create_magento_archive() {
    status_message "INFO" "Création d'une archive des fichiers Magento sur le serveur source..."
    
    # Création du répertoire temporaire sur le serveur source s'il n'existe pas
    if command -v sshpass &> /dev/null; then
        sshpass -p "${SSH_PASSWORD}" ssh ${SOURCE_USER}@${SOURCE_SERVER} "mkdir -p ${TEMP_DIR}"
        
        # Création de l'archive
        status_message "INFO" "Création de l'archive ${TEMP_DIR}/${ARCHIVE_NAME}..."
        sshpass -p "${SSH_PASSWORD}" ssh ${SOURCE_USER}@${SOURCE_SERVER} "cd ${SOURCE_MAGENTO_PATH} && tar -czf ${TEMP_DIR}/${ARCHIVE_NAME} --exclude='var/cache/*' --exclude='var/page_cache/*' --exclude='var/session/*' --exclude='var/log/*' --exclude='var/report/*' --exclude='var/tmp/*' ."
    else
        ssh ${SOURCE_USER}@${SOURCE_SERVER} "mkdir -p ${TEMP_DIR}"
        
        # Création de l'archive
        status_message "INFO" "Création de l'archive ${TEMP_DIR}/${ARCHIVE_NAME}..."
        ssh ${SOURCE_USER}@${SOURCE_SERVER} "cd ${SOURCE_MAGENTO_PATH} && tar -czf ${TEMP_DIR}/${ARCHIVE_NAME} --exclude='var/cache/*' --exclude='var/page_cache/*' --exclude='var/session/*' --exclude='var/log/*' --exclude='var/report/*' --exclude='var/tmp/*' ."
    fi
    
    if [ $? -ne 0 ]; then
        status_message "ERROR" "Échec de la création de l'archive."
        exit 1
    fi
    
    status_message "OK" "Archive créée avec succès."
}

# Fonction pour transférer l'archive vers le serveur de destination
transfer_archive() {
    status_message "INFO" "Transfert de l'archive vers le serveur de destination..."
    
    # Transfert de l'archive
    if command -v sshpass &> /dev/null; then
        sshpass -p "${SSH_PASSWORD}" scp ${SOURCE_USER}@${SOURCE_SERVER}:${TEMP_DIR}/${ARCHIVE_NAME} ${TEMP_ARCHIVE}
    else
        scp ${SOURCE_USER}@${SOURCE_SERVER}:${TEMP_DIR}/${ARCHIVE_NAME} ${TEMP_ARCHIVE}
    fi
    
    if [ $? -ne 0 ]; then
        status_message "ERROR" "Échec du transfert de l'archive."
        exit 1
    fi
    
    # Copie de l'archive dans le répertoire de sauvegarde
    cp ${TEMP_ARCHIVE} ${BACKUP_ARCHIVE}
    
    status_message "OK" "Archive transférée avec succès."
}

# Fonction pour extraire l'archive dans le répertoire de destination
extract_archive() {
    status_message "INFO" "Extraction de l'archive dans le répertoire de destination..."
    
    # Extraction de l'archive
    tar -xzf ${TEMP_ARCHIVE} -C ${DEST_MAGENTO_PATH}
    
    if [ $? -ne 0 ]; then
        status_message "ERROR" "Échec de l'extraction de l'archive."
        exit 1
    fi
    
    status_message "OK" "Archive extraite avec succès."
}

# Fonction pour configurer les permissions des fichiers Magento
set_magento_permissions() {
    status_message "INFO" "Configuration des permissions pour les fichiers Magento..."
    
    # Mise à jour des propriétaires et groupes
    chown -R ${DEST_USER}:${DEST_GROUP} ${DEST_MAGENTO_PATH}
    
    # Permissions spécifiques pour les répertoires
    find ${DEST_MAGENTO_PATH} -type d -exec chmod 755 {} \;
    
    # Permissions spécifiques pour les fichiers
    find ${DEST_MAGENTO_PATH} -type f -exec chmod 644 {} \;
    
    # Permissions spéciales pour les répertoires qui doivent être inscriptibles
    chmod -R 775 ${DEST_MAGENTO_PATH}/var
    chmod -R 775 ${DEST_MAGENTO_PATH}/pub/media
    chmod -R 775 ${DEST_MAGENTO_PATH}/pub/static
    chmod -R 775 ${DEST_MAGENTO_PATH}/generated
    chmod -R 775 ${DEST_MAGENTO_PATH}/app/etc
    
    # S'assurer que les fichiers bin/magento sont exécutables
    chmod +x ${DEST_MAGENTO_PATH}/bin/magento
    
    # Mise à jour des propriétaires et groupes pour les répertoires inscriptibles
    chown -R ${DEST_USER}:${DEST_GROUP} ${DEST_MAGENTO_PATH}/var
    chown -R ${DEST_USER}:${DEST_GROUP} ${DEST_MAGENTO_PATH}/pub/media
    chown -R ${DEST_USER}:${DEST_GROUP} ${DEST_MAGENTO_PATH}/pub/static
    chown -R ${DEST_USER}:${DEST_GROUP} ${DEST_MAGENTO_PATH}/generated
    chown -R ${DEST_USER}:${DEST_GROUP} ${DEST_MAGENTO_PATH}/app/etc
    
    status_message "OK" "Permissions configurées avec succès."
}

# Fonction pour mettre à jour la configuration Magento
update_magento_config() {
    status_message "INFO" "Mise à jour de la configuration Magento..."
    
    # Sauvegarde du fichier env.php
    ENV_PHP="${DEST_MAGENTO_PATH}/app/etc/env.php"
    if [ -f "$ENV_PHP" ]; then
        cp "$ENV_PHP" "${ENV_PHP}.bak"
    fi
    
    # Création d'un script PHP temporaire pour mettre à jour uniquement la connexion BDD
    TMP_PHP_SCRIPT="/tmp/update_env_php.php"
    cat > $TMP_PHP_SCRIPT << 'EOF'
<?php
// Chargement de la configuration existante
$envFile = $argv[1];
$dbName = $argv[2];
$dbUser = $argv[3];
$dbPassword = $argv[4];

if (!file_exists($envFile)) {
    echo "Le fichier env.php n'existe pas.\n";
    exit(1);
}

$config = include $envFile;

// Mise à jour de la connexion à la base de données
if (isset($config['db']['connection']['default'])) {
    $config['db']['connection']['default']['dbname'] = $dbName;
    $config['db']['connection']['default']['username'] = $dbUser;
    $config['db']['connection']['default']['password'] = $dbPassword;
    echo "Connexion base de données mise à jour: $dbName, $dbUser\n";
}

// Écriture de la configuration mise à jour
$configContent = "<?php\nreturn " . var_export($config, true) . ";\n";
file_put_contents($envFile, $configContent);

echo "Configuration base de données mise à jour avec succès.\n";
EOF
    
    # Exécution du script PHP pour mettre à jour env.php
    php $TMP_PHP_SCRIPT "$ENV_PHP" "$DEST_DATABASE" "$DEST_DATABASE_USER" "$DEST_DATABASE_PASSWORD"
    
    if [ $? -ne 0 ]; then
        status_message "ERROR" "Échec de la mise à jour de la configuration Magento."
        exit 1
    fi
    
    # Suppression du script temporaire
    rm -f $TMP_PHP_SCRIPT
    
    # Mise à jour des permissions
    chown ${DEST_USER}:${DEST_GROUP} "$ENV_PHP"
    
    status_message "OK" "Configuration Magento mise à jour avec succès."
}

# Fonction pour nettoyer les fichiers temporaires
cleanup() {
    status_message "INFO" "Nettoyage des fichiers temporaires..."
    
    # Suppression de l'archive temporaire
    rm -f ${TEMP_ARCHIVE}
    
    status_message "OK" "Nettoyage terminé."
}

# Fonction principale
main() {
    status_message "INFO" "Début de la migration de Magento..."
    
    # Vérification des prérequis
    check_prerequisites
    
    # Vérification des archives existantes
    if check_existing_archives; then
        status_message "INFO" "Utilisation de l'archive existante: ${ARCHIVE_NAME}"
    else
        # Création de l'archive
        create_magento_archive
    fi
    
    # Transfert de l'archive
    transfer_archive
    
    # Extraction de l'archive
    extract_archive
    
    # Configuration des permissions
    set_magento_permissions
    
    # Mise à jour de la configuration
    update_magento_config
    
    # Nettoyage du cache Magento et optimisation
    status_message "INFO" "Voulez-vous nettoyer le cache Magento et optimiser l'installation ? (o/n)"
    read -r response
    if [[ "$response" =~ ^[Oo]$ ]]; then
        clean_magento_cache
    else
        status_message "INFO" "Nettoyage du cache ignoré."
    fi
    
    # Nettoyage
    cleanup
    
    status_message "OK" "Migration de Magento terminée avec succès."
    status_message "INFO" "Magento a été migré vers ${DEST_MAGENTO_PATH}"
    status_message "INFO" "Une sauvegarde de l'archive a été créée dans ${BACKUP_ARCHIVE}"
    status_message "INFO" "Varnish a été configuré comme full page cache"
    status_message "INFO" "Redis a été configuré pour les caches et les sessions"
}

# Exécution de la fonction principale
main
