#!/usr/bin/env php
<?php

/**
 * Script de migration de l'arborescence des uploads
 * Réorganise les fichiers existants vers la nouvelle structure simplifiée
 * 
 * Ancienne structure : uploads/entites/{id}/* et uploads/{id}/*
 * Nouvelle structure : uploads/{id}/*
 * 
 * Usage: php scripts/migrate_uploads_structure.php [--dry-run]
 */

declare(strict_types=1);

// Chemin de base des uploads
const BASE_PATH = '/var/www/geosector/api/uploads';
const LOG_FILE = '/var/www/geosector/api/logs/migration_uploads_' . date('Ymd_His') . '.log';

// Mode dry-run (simulation sans modification)
$dryRun = in_array('--dry-run', $argv);

// Fonction pour logger
function logMessage(string $message, string $level = 'INFO'): void {
    $timestamp = date('Y-m-d H:i:s');
    $log = "[$timestamp] [$level] $message" . PHP_EOL;
    echo $log;
    if (!$GLOBALS['dryRun']) {
        file_put_contents(LOG_FILE, $log, FILE_APPEND);
    }
}

// Fonction pour déplacer un fichier ou dossier
function moveItem(string $source, string $destination): bool {
    global $dryRun;
    
    if (!file_exists($source)) {
        logMessage("Source n'existe pas: $source", 'WARNING');
        return false;
    }
    
    // Créer le dossier de destination si nécessaire
    $destDir = dirname($destination);
    if (!is_dir($destDir)) {
        logMessage("Création du dossier: $destDir");
        if (!$dryRun) {
            mkdir($destDir, 0775, true);
            chown($destDir, 'nginx');
            chgrp($destDir, 'nobody');
        }
    }
    
    // Déplacer l'élément
    logMessage("Déplacement: $source -> $destination");
    if (!$dryRun) {
        if (is_dir($source)) {
            // Pour un dossier, utiliser rename
            return rename($source, $destination);
        } else {
            // Pour un fichier
            return rename($source, $destination);
        }
    }
    
    return true;
}

// Fonction pour copier récursivement un dossier
function copyDirectory(string $source, string $dest): bool {
    global $dryRun;
    
    if (!is_dir($source)) {
        return false;
    }
    
    if (!$dryRun) {
        if (!is_dir($dest)) {
            mkdir($dest, 0775, true);
            chown($dest, 'nginx');
            chgrp($dest, 'nobody');
        }
    }
    
    $dir = opendir($source);
    while (($file = readdir($dir)) !== false) {
        if ($file === '.' || $file === '..') {
            continue;
        }
        
        $srcPath = "$source/$file";
        $destPath = "$dest/$file";
        
        if (is_dir($srcPath)) {
            copyDirectory($srcPath, $destPath);
        } else {
            logMessage("Copie: $srcPath -> $destPath");
            if (!$dryRun) {
                copy($srcPath, $destPath);
                chmod($destPath, 0664);
                chown($destPath, 'nginx');
                chgrp($destPath, 'nobody');
            }
        }
    }
    closedir($dir);
    
    return true;
}

// Fonction principale de migration
function migrateUploads(): void {
    global $dryRun;
    
    logMessage("=== Début de la migration des uploads ===");
    logMessage($dryRun ? "MODE DRY-RUN (simulation)" : "MODE RÉEL (modifications effectives)");
    
    // 1. Migrer uploads/entites/* vers uploads/*
    $entitesPath = BASE_PATH . '/entites';
    if (is_dir($entitesPath)) {
        logMessage("Traitement du dossier entites/");
        
        $entites = scandir($entitesPath);
        foreach ($entites as $entiteId) {
            if ($entiteId === '.' || $entiteId === '..') continue;
            
            $oldPath = "$entitesPath/$entiteId";
            $newPath = BASE_PATH . "/$entiteId";
            
            if (!is_dir($oldPath)) continue;
            
            logMessage("Migration entité $entiteId");
            
            // Si le dossier destination existe déjà, fusionner
            if (is_dir($newPath)) {
                logMessage("Le dossier $entiteId existe déjà à la racine, fusion nécessaire", 'INFO');
                
                // Migrer les sous-dossiers
                $subDirs = scandir($oldPath);
                foreach ($subDirs as $subDir) {
                    if ($subDir === '.' || $subDir === '..') continue;
                    
                    $oldSubPath = "$oldPath/$subDir";
                    $newSubPath = "$newPath/$subDir";
                    
                    if ($subDir === 'operations') {
                        // Traiter spécialement le dossier operations
                        migrateOperations($oldSubPath, $newSubPath);
                    } else {
                        // Pour logo et recus, déplacer directement
                        if (!is_dir($newSubPath)) {
                            moveItem($oldSubPath, $newSubPath);
                        } else {
                            logMessage("Le dossier $newSubPath existe déjà, fusion du contenu");
                            copyDirectory($oldSubPath, $newSubPath);
                            if (!$dryRun) {
                                // Supprimer l'ancien après copie
                                exec("rm -rf " . escapeshellarg($oldSubPath));
                            }
                        }
                    }
                }
            } else {
                // Déplacer simplement le dossier entier
                moveItem($oldPath, $newPath);
            }
        }
        
        // Supprimer le dossier entites vide
        if (!$dryRun) {
            if (count(scandir($entitesPath)) === 2) { // Seulement . et ..
                rmdir($entitesPath);
                logMessage("Suppression du dossier entites/ vide");
            }
        }
    }
    
    // 2. Nettoyer la structure des dossiers operations
    logMessage("Nettoyage de la structure des dossiers operations");
    cleanupOperationsStructure();
    
    logMessage("=== Migration terminée ===");
    if (!$dryRun) {
        logMessage("Logs sauvegardés dans: " . LOG_FILE);
    }
}

// Fonction pour migrer le dossier operations avec simplification
function migrateOperations(string $oldPath, string $newPath): void {
    global $dryRun;
    
    if (!is_dir($oldPath)) return;
    
    logMessage("Migration du dossier operations: $oldPath");
    
    if (!$dryRun && !is_dir($newPath)) {
        mkdir($newPath, 0775, true);
        chown($newPath, 'nginx');
        chgrp($newPath, 'nobody');
    }
    
    $operations = scandir($oldPath);
    foreach ($operations as $opId) {
        if ($opId === '.' || $opId === '..') continue;
        
        $oldOpPath = "$oldPath/$opId";
        $newOpPath = "$newPath/$opId";
        
        // Simplifier la structure: déplacer les xlsx directement dans operations/{id}/
        if (is_dir("$oldOpPath/documents/exports/excel")) {
            $excelPath = "$oldOpPath/documents/exports/excel";
            $files = scandir($excelPath);
            
            foreach ($files as $file) {
                if ($file === '.' || $file === '..' || !str_ends_with($file, '.xlsx')) continue;
                
                $oldFilePath = "$excelPath/$file";
                $newFilePath = "$newOpPath/$file";
                
                logMessage("Déplacement Excel: $oldFilePath -> $newFilePath");
                
                if (!$dryRun) {
                    if (!is_dir($newOpPath)) {
                        mkdir($newOpPath, 0775, true);
                        chown($newOpPath, 'nginx');
                        chgrp($newOpPath, 'nobody');
                    }
                    rename($oldFilePath, $newFilePath);
                    chmod($newFilePath, 0664);
                    chown($newFilePath, 'nginx');
                    chgrp($newFilePath, 'nobody');
                }
            }
        }
    }
}

// Fonction pour nettoyer la structure après migration
function cleanupOperationsStructure(): void {
    global $dryRun;
    
    $uploadsDir = BASE_PATH;
    $entites = scandir($uploadsDir);
    
    foreach ($entites as $entiteId) {
        if ($entiteId === '.' || $entiteId === '..' || $entiteId === 'entites') continue;
        
        $operationsPath = "$uploadsDir/$entiteId/operations";
        if (!is_dir($operationsPath)) continue;
        
        $operations = scandir($operationsPath);
        foreach ($operations as $opId) {
            if ($opId === '.' || $opId === '..') continue;
            
            $opPath = "$operationsPath/$opId";
            
            // Supprimer l'ancienne structure documents/exports/excel si elle est vide
            $oldStructure = "$opPath/documents";
            if (is_dir($oldStructure)) {
                logMessage("Suppression de l'ancienne structure: $oldStructure");
                if (!$dryRun) {
                    exec("rm -rf " . escapeshellarg($oldStructure));
                }
            }
        }
    }
}

// Vérifier les permissions
if (!is_dir(BASE_PATH)) {
    die("ERREUR: Le dossier " . BASE_PATH . " n'existe pas\n");
}

if (!is_writable(BASE_PATH) && !$dryRun) {
    die("ERREUR: Le dossier " . BASE_PATH . " n'est pas accessible en écriture\n");
}

// Lancer la migration
try {
    migrateUploads();
    
    if ($dryRun) {
        echo "\n";
        echo "========================================\n";
        echo "SIMULATION TERMINÉE\n";
        echo "Pour exécuter réellement la migration:\n";
        echo "php " . $argv[0] . "\n";
        echo "========================================\n";
    } else {
        echo "\n";
        echo "========================================\n";
        echo "MIGRATION TERMINÉE AVEC SUCCÈS\n";
        echo "Vérifiez les logs: " . LOG_FILE . "\n";
        echo "========================================\n";
    }
} catch (Exception $e) {
    logMessage("ERREUR FATALE: " . $e->getMessage(), 'ERROR');
    exit(1);
}