<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;

/**
 * Commande de nettoyage automatique du système
 * 
 * Nettoie les fichiers temporaires, logs anciens, sessions expirées, etc.
 * Exécutée quotidiennement à 03:00 via le scheduler.
 * 
 * Ce qui est nettoyé:
 * - Logs Laravel > 30 jours
 * - Sessions expirées (DB)
 * - Cache périmé
 * - Fichiers temporaires > 7 jours
 * - Images orphelines (non liées à des produits)
 * - Notifications lues > 90 jours
 * - Activity logs > 180 jours
 */
class CleanupSystem extends Command
{
    protected $signature = 'system:cleanup 
                            {--dry-run : Simuler sans supprimer}
                            {--verbose : Afficher les détails}';

    protected $description = 'Nettoyer les fichiers temporaires, logs anciens et données périmées';

    protected array $stats = [
        'logs_deleted' => 0,
        'sessions_deleted' => 0,
        'cache_cleared' => false,
        'temp_files_deleted' => 0,
        'temp_size_freed' => 0,
        'orphan_images_deleted' => 0,
        'notifications_deleted' => 0,
        'activity_logs_deleted' => 0,
    ];

    public function handle()
    {
        $isDryRun = $this->option('dry-run');
        $isVerbose = $this->option('verbose');
        
        $this->info('=== Nettoyage Système ===');
        $this->info('Date: ' . now()->format('d/m/Y H:i:s'));
        
        if ($isDryRun) {
            $this->warn('Mode simulation activé - aucun fichier ne sera supprimé.');
        }

        $this->newLine();

        // 1. Nettoyer les logs Laravel
        $this->cleanupLogs($isDryRun, $isVerbose);
        
        // 2. Nettoyer les sessions expirées (si stockées en DB)
        $this->cleanupSessions($isDryRun);
        
        // 3. Nettoyer le cache
        $this->cleanupCache($isDryRun);
        
        // 4. Nettoyer les fichiers temporaires
        $this->cleanupTempFiles($isDryRun, $isVerbose);
        
        // 5. Nettoyer les notifications lues anciennes
        $this->cleanupNotifications($isDryRun);
        
        // 6. Nettoyer les activity logs anciens
        $this->cleanupActivityLogs($isDryRun);
        
        // 7. Optimiser les tables (optionnel)
        $this->optimizeTables($isDryRun);

        // Afficher le résumé
        $this->displaySummary();

        // Logger le nettoyage
        Log::info('Nettoyage système effectué', [
            'dry_run' => $isDryRun,
            'stats' => $this->stats,
        ]);

        return Command::SUCCESS;
    }

    /**
     * Nettoyer les anciens logs Laravel
     */
    protected function cleanupLogs(bool $isDryRun, bool $isVerbose): void
    {
        $this->info('📄 Nettoyage des logs...');
        
        $logPath = storage_path('logs');
        $maxAgeDays = 30;
        $cutoffDate = now()->subDays($maxAgeDays);
        
        if (!File::isDirectory($logPath)) {
            $this->warn('  Dossier logs non trouvé');
            return;
        }

        $files = File::glob($logPath . '/*.log');
        
        foreach ($files as $file) {
            $fileDate = File::lastModified($file);
            $fileName = basename($file);
            
            // Ne pas supprimer le fichier log actuel
            if ($fileName === 'laravel.log') {
                // Vérifier la taille du fichier
                $sizeMB = round(File::size($file) / 1024 / 1024, 2);
                if ($sizeMB > 50) {
                    $this->warn("  ⚠️ laravel.log fait {$sizeMB} MB - considérer une rotation");
                }
                continue;
            }
            
            // Supprimer les logs datés de plus de 30 jours
            if (\Carbon\Carbon::createFromTimestamp($fileDate)->lt($cutoffDate)) {
                if ($isVerbose) {
                    $this->line("  - Suppression: {$fileName}");
                }
                
                if (!$isDryRun) {
                    File::delete($file);
                }
                
                $this->stats['logs_deleted']++;
            }
        }
        
        $this->info("  ✓ {$this->stats['logs_deleted']} fichier(s) log supprimé(s)");
    }

    /**
     * Nettoyer les sessions expirées (si en DB)
     */
    protected function cleanupSessions(bool $isDryRun): void
    {
        $this->info('🔐 Nettoyage des sessions...');
        
        // Vérifier si les sessions sont en base de données
        if (config('session.driver') !== 'database') {
            $this->line('  Sessions non stockées en DB - ignoré');
            return;
        }

        $sessionTable = config('session.table', 'sessions');
        $lifetime = config('session.lifetime', 120); // minutes
        
        $query = DB::table($sessionTable)
            ->where('last_activity', '<', now()->subMinutes($lifetime)->timestamp);
        
        $count = $query->count();
        
        if (!$isDryRun && $count > 0) {
            $query->delete();
        }
        
        $this->stats['sessions_deleted'] = $count;
        $this->info("  ✓ {$count} session(s) expirée(s) supprimée(s)");
    }

    /**
     * Nettoyer le cache
     */
    protected function cleanupCache(bool $isDryRun): void
    {
        $this->info('🗄️ Nettoyage du cache...');
        
        if (!$isDryRun) {
            // Vider le cache des vues compilées
            \Illuminate\Support\Facades\Artisan::call('view:clear');
            
            // Vider le cache de configuration (uniquement en dev)
            // Artisan::call('config:clear');
            
            // Nettoyer le cache des routes (seulement si pas en cache)
            // Artisan::call('route:clear');
            
            $this->stats['cache_cleared'] = true;
        }
        
        // Nettoyer les fichiers de cache temporaires
        $cachePath = storage_path('framework/cache/data');
        if (File::isDirectory($cachePath)) {
            $files = File::allFiles($cachePath);
            $deletedCount = 0;
            
            foreach ($files as $file) {
                // Supprimer les fichiers cache de plus de 24h
                if ($file->getMTime() < now()->subDay()->timestamp) {
                    if (!$isDryRun) {
                        File::delete($file->getPathname());
                    }
                    $deletedCount++;
                }
            }
            
            if ($deletedCount > 0) {
                $this->line("  - {$deletedCount} fichier(s) cache périmé(s) supprimé(s)");
            }
        }
        
        $this->info('  ✓ Cache nettoyé');
    }

    /**
     * Nettoyer les fichiers temporaires
     */
    protected function cleanupTempFiles(bool $isDryRun, bool $isVerbose): void
    {
        $this->info('📁 Nettoyage des fichiers temporaires...');
        
        $tempPaths = [
            storage_path('app/tmp'),
            storage_path('framework/testing'),
            storage_path('app/public/tmp'),
        ];
        
        $maxAgeDays = 7;
        $cutoffDate = now()->subDays($maxAgeDays);
        $totalSize = 0;
        
        foreach ($tempPaths as $path) {
            if (!File::isDirectory($path)) {
                continue;
            }
            
            $files = File::allFiles($path);
            
            foreach ($files as $file) {
                if (\Carbon\Carbon::createFromTimestamp($file->getMTime())->lt($cutoffDate)) {
                    $totalSize += $file->getSize();
                    
                    if ($isVerbose) {
                        $this->line("  - Suppression: " . $file->getRelativePathname());
                    }
                    
                    if (!$isDryRun) {
                        File::delete($file->getPathname());
                    }
                    
                    $this->stats['temp_files_deleted']++;
                }
            }
        }
        
        $this->stats['temp_size_freed'] = $totalSize;
        $sizeMB = round($totalSize / 1024 / 1024, 2);
        
        $this->info("  ✓ {$this->stats['temp_files_deleted']} fichier(s) temporaire(s) supprimé(s) ({$sizeMB} MB)");
    }

    /**
     * Nettoyer les anciennes notifications lues
     */
    protected function cleanupNotifications(bool $isDryRun): void
    {
        $this->info('🔔 Nettoyage des notifications...');
        
        $maxAgeDays = 90;
        
        // Supprimer les notifications lues de plus de 90 jours
        $query = DB::table('notifications')
            ->whereNotNull('read_at')
            ->where('read_at', '<', now()->subDays($maxAgeDays));
        
        $count = $query->count();
        
        if (!$isDryRun && $count > 0) {
            $query->delete();
        }
        
        $this->stats['notifications_deleted'] = $count;
        $this->info("  ✓ {$count} notification(s) ancienne(s) supprimée(s)");
    }

    /**
     * Nettoyer les activity logs anciens
     */
    protected function cleanupActivityLogs(bool $isDryRun): void
    {
        $this->info('📝 Nettoyage des logs d\'activité...');
        
        $maxAgeDays = 180; // 6 mois
        
        // Vérifier si la table existe
        if (!DB::getSchemaBuilder()->hasTable('activity_logs')) {
            $this->line('  Table activity_logs non trouvée - ignoré');
            return;
        }
        
        $query = DB::table('activity_logs')
            ->where('created_at', '<', now()->subDays($maxAgeDays));
        
        $count = $query->count();
        
        if (!$isDryRun && $count > 0) {
            // Supprimer par lots pour éviter les timeout
            $query->orderBy('id')->limit(10000)->delete();
        }
        
        $this->stats['activity_logs_deleted'] = $count;
        $this->info("  ✓ {$count} log(s) d'activité ancien(s) supprimé(s)");
    }

    /**
     * Optimiser les tables de la base de données
     */
    protected function optimizeTables(bool $isDryRun): void
    {
        $this->info('⚡ Optimisation des tables...');
        
        if ($isDryRun) {
            $this->line('  Optimisation ignorée en mode simulation');
            return;
        }

        // Tables à optimiser
        $tables = [
            'orders',
            'commissions',
            'notifications',
            'activity_logs',
            'wallet_transactions',
        ];

        $driver = DB::connection()->getDriverName();
        
        foreach ($tables as $table) {
            if (!DB::getSchemaBuilder()->hasTable($table)) {
                continue;
            }
            
            try {
                if ($driver === 'mysql') {
                    DB::statement("OPTIMIZE TABLE {$table}");
                }
                // Pour PostgreSQL ou SQLite, différentes commandes...
            } catch (\Exception $e) {
                // Ignorer les erreurs d'optimisation
                Log::debug("Optimisation de {$table} ignorée: " . $e->getMessage());
            }
        }
        
        $this->info('  ✓ Tables optimisées');
    }

    /**
     * Afficher le résumé du nettoyage
     */
    protected function displaySummary(): void
    {
        $this->newLine();
        $this->info('=== Résumé du Nettoyage ===');
        
        $this->table(
            ['Métrique', 'Valeur'],
            [
                ['Fichiers log supprimés', $this->stats['logs_deleted']],
                ['Sessions supprimées', $this->stats['sessions_deleted']],
                ['Cache nettoyé', $this->stats['cache_cleared'] ? 'Oui' : 'Non'],
                ['Fichiers temp supprimés', $this->stats['temp_files_deleted']],
                ['Espace libéré', round($this->stats['temp_size_freed'] / 1024 / 1024, 2) . ' MB'],
                ['Notifications supprimées', $this->stats['notifications_deleted']],
                ['Logs activité supprimés', $this->stats['activity_logs_deleted']],
            ]
        );
        
        $this->newLine();
        $this->info('✅ Nettoyage terminé !');
    }
}
