<?php

/**
 * Configuration pour les scripts de migration et utilitaires
 */

// Configuration SSH pour accéder au serveur distant
define('SSH_HOST', '212.83.164.111'); // Adresse du serveur distant
define('SSH_PORT', 52266);                          // Port SSH (généralement 22)
define('SSH_USER', 'root');                    // Nom d'utilisateur SSH - à ajuster selon votre utilisateur
define('SSH_KEY_FILE', '/root/.ssh/id_rsa_db2');  // Chemin vers la clé SSH privée

// Configuration de la base de données source (MySQL geosector) sur le serveur distant
define('REMOTE_DB_HOST', '127.0.0.1');           // Hôte de la base sur le serveur distant (utiliser 127.0.0.1 au lieu de localhost)
define('REMOTE_DB_PORT', 3306);                  // Port de la base sur le serveur distant
define('SOURCE_DB_HOST', '127.0.0.1');           // Hôte local pour le tunnel SSH (utiliser 127.0.0.1 au lieu de localhost)
define('SOURCE_DB_NAME', 'geosector');           // Nom de la base de données source (utiliser une des bases disponibles listées)
define('SOURCE_DB_USER', 'geo_front_user');      // Utilisateur de la base de données source
define('SOURCE_DB_PASS', 'd66,GeoFront.User');        // Mot de passe de la base de données source
define('SOURCE_DB_PORT', 13306);                 // Port local pour le tunnel SSH

// Configuration de la base de données cible (MariaDB geo_app)
define('TARGET_DB_HOST', 'localhost');
define('TARGET_DB_NAME', 'geo_app');
define('TARGET_DB_USER', 'geo_app_user');
define('TARGET_DB_PASS', 'QO:96df*?k{4W6m');
define('TARGET_DB_PORT', 3306);

// Chemin vers l'API pour utiliser les services de chiffrement
define('API_ROOT', dirname(__DIR__));

// Inclure les services de l'API pour le chiffrement/déchiffrement
require_once API_ROOT . '/bootstrap.php';

/**
 * Fonction utilitaire pour établir un tunnel SSH vers le serveur distant
 */
function createSshTunnel() {
    // Vérifier si un tunnel est déjà en cours d'exécution
    $checkCommand = "ps aux | grep 'ssh -[vf]* -N -L " . SOURCE_DB_PORT . ":' | grep -v grep";
    exec($checkCommand, $output, $return_var);

    if (empty($output)) {
        // Créer le tunnel SSH avec options de sécurité
        $command = "ssh -f -N -o StrictHostKeyChecking=no -L " . SOURCE_DB_PORT . ":" . REMOTE_DB_HOST . ":" . REMOTE_DB_PORT . " -p " . SSH_PORT . " " . SSH_USER . "@" . SSH_HOST . " -i " . SSH_KEY_FILE;

        exec($command, $output, $return_var);

        if ($return_var !== 0) {
            logOperation("Erreur lors de la création du tunnel SSH", "ERROR");
            return false;
        }

        // Attendre que le tunnel soit établi
        sleep(2);
        logOperation("Tunnel SSH établi sur le port local " . SOURCE_DB_PORT, "INFO");

        // Vérification simple du tunnel
        $checkTunnel = "netstat -an | grep " . SOURCE_DB_PORT . " | grep LISTEN";
        exec($checkTunnel, $tunnelOutput);

        if (empty($tunnelOutput)) {
            logOperation("Le tunnel semble être créé mais le port n'est pas en écoute", "WARNING");
        }
    } else {
        logOperation("Un tunnel SSH est déjà en cours d'exécution", "INFO");
    }

    return true;
}

/**
 * Fonction utilitaire pour fermer le tunnel SSH
 */
function closeSshTunnel() {
    // Utiliser une expression régulière plus large pour capturer tous les processus SSH de tunnel
    $command = "ps aux | grep 'ssh -[vf]* -N -L " . SOURCE_DB_PORT . ":' | grep -v grep | awk '{print $2}' | xargs -r kill 2>/dev/null";
    exec($command);
    logOperation("Tunnel SSH fermé", "INFO");
}

/**
 * Fonction utilitaire pour se connecter à la base de données source via SSH
 */
function getSourceConnection() {
    try {
        // Établir le tunnel SSH
        if (!createSshTunnel()) {
            throw new PDOException("Impossible d'établir le tunnel SSH");
        }

        // Options de connexion PDO
        $options = [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
            PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8mb4'
        ];

        // Ajouter l'option pour MySQL 8
        if (defined('PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT')) {
            $options[PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = false;
        }

        try {
            // D'abord vérifier si la base existe
            $tempDsn = 'mysql:host=' . SOURCE_DB_HOST . ';port=' . SOURCE_DB_PORT;
            $tempPdo = new PDO($tempDsn, SOURCE_DB_USER, SOURCE_DB_PASS, $options);

            $stmt = $tempPdo->query("SHOW DATABASES");
            $databases = $stmt->fetchAll(PDO::FETCH_COLUMN);

            if (!in_array(SOURCE_DB_NAME, $databases)) {
                logOperation("Base de données '" . SOURCE_DB_NAME . "' introuvable. Bases disponibles: " . implode(", ", $databases), "ERROR");
                throw new PDOException("Base de données '" . SOURCE_DB_NAME . "' introuvable");
            }

            // Se connecter à la base spécifique
            $dsn = 'mysql:host=' . SOURCE_DB_HOST . ';dbname=' . SOURCE_DB_NAME . ';port=' . SOURCE_DB_PORT;
            $pdo = new PDO($dsn, SOURCE_DB_USER, SOURCE_DB_PASS, $options);

            logOperation("Connexion établie à la base '" . SOURCE_DB_NAME . "'", "INFO");
            return $pdo;
        } catch (PDOException $e) {
            logOperation("Erreur de connexion: " . $e->getMessage(), "ERROR");
            throw $e;
        }
    } catch (PDOException $e) {
        closeSshTunnel();
        throw new Exception("Erreur de connexion à la base source: " . $e->getMessage());
    }
}

/**
 * Fonction utilitaire pour se connecter à la base de données cible
 */
function getTargetConnection() {
    try {
        $dsn = 'mysql:host=' . TARGET_DB_HOST . ';dbname=' . TARGET_DB_NAME . ';port=' . TARGET_DB_PORT;
        $pdo = new PDO($dsn, TARGET_DB_USER, TARGET_DB_PASS, [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
            PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8mb4'
        ]);
        return $pdo;
    } catch (PDOException $e) {
        die('Erreur de connexion à la base cible: ' . $e->getMessage());
    }
}

/**
 * Fonction pour journaliser les opérations
 */
function logOperation($message, $level = 'INFO') {
    $logFile = __DIR__ . '/logs/migration_' . date('Y-m-d') . '.log';
    $logDir = dirname($logFile);

    if (!is_dir($logDir)) {
        mkdir($logDir, 0755, true);
    }

    $timestamp = date('Y-m-d H:i:s');
    $logMessage = "[$timestamp] [$level] $message" . PHP_EOL;
    file_put_contents($logFile, $logMessage, FILE_APPEND);

    if (php_sapi_name() === 'cli') {
        echo $logMessage;
    }
}
