<?php

namespace App\Console\Commands;

use App\Models\Features\Feature;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;

class CleanupUnusedFeatureImages extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'features:cleanup-images {--dry-run : Simular sin eliminar archivos}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Elimina imágenes no utilizadas de las features';

    /**
     * Execute the console command.
     */
    public function handle()
    {
        $dryRun = $this->option('dry-run');
        
        if ($dryRun) {
            $this->info('🔍 Modo DRY-RUN: No se eliminarán archivos');
        } else {
            $this->warn('⚠️  Se eliminarán archivos reales');
        }

        $this->info('Escaneando directorio de features...');
        
        $featuresBasePath = 'features';
        $disk = Storage::disk('public');
        
        if (!$disk->exists($featuresBasePath)) {
            $this->info('No existe el directorio de features.');
            return Command::SUCCESS;
        }

        // Obtener todas las features con sus imágenes
        $features = Feature::all();
        $usedImages = [];
        $totalDeleted = 0;
        $totalSize = 0;

        // Recopilar todas las imágenes en uso
        foreach ($features as $feature) {
            $featureId = $feature->id;
            $featurePath = "features/{$featureId}";

            // Imágenes estructurales
            if ($feature->thumbnail_image) {
                $usedImages[] = $feature->thumbnail_image;
            }
            if ($feature->header_image) {
                $usedImages[] = $feature->header_image;
            }

            // Extraer URLs de imágenes del content_html
            if ($feature->content_html) {
                $html = $feature->content_html;
                
                // Buscar todas las etiquetas img
                preg_match_all('/<img[^>]+src=["\']([^"\']+)["\'][^>]*>/i', $html, $matches);
                
                if (!empty($matches[1])) {
                    foreach ($matches[1] as $url) {
                        // Convertir URL pública a ruta relativa
                        $relativePath = $this->urlToRelativePath($url);
                        if ($relativePath && Str::startsWith($relativePath, $featurePath)) {
                            $usedImages[] = $relativePath;
                        }
                    }
                }
            }
        }

        $usedImages = array_unique($usedImages);
        $this->info("Imágenes en uso encontradas: " . count($usedImages));

        // Escanear directorio de features
        $directories = $disk->directories($featuresBasePath);
        
        foreach ($directories as $directory) {
            // Extraer feature_id del directorio (features/123 o features/temp/123)
            if (preg_match('/features\/(\d+)/', $directory, $matches)) {
                $featureId = (int) $matches[1];
                
                $this->line("Procesando feature ID: {$featureId}");
                
                // Obtener todos los archivos en este directorio (recursivo)
                $files = $disk->allFiles($directory);
                
                foreach ($files as $file) {
                    // Verificar si el archivo está en uso
                    if (!in_array($file, $usedImages)) {
                        $fileSize = $disk->size($file);
                        $totalSize += $fileSize;
                        
                        if ($dryRun) {
                            $this->line("  [DRY-RUN] Eliminaría: {$file} (" . $this->formatBytes($fileSize) . ")");
                        } else {
                            if ($disk->delete($file)) {
                                $this->line("  ✓ Eliminado: {$file} (" . $this->formatBytes($fileSize) . ")");
                                $totalDeleted++;
                            } else {
                                $this->error("  ✗ Error al eliminar: {$file}");
                            }
                        }
                    }
                }
                
                // Eliminar directorios vacíos (excepto el directorio base)
                if (!$dryRun) {
                    $this->cleanupEmptyDirectories($disk, $directory);
                }
            }
        }

        // Limpiar directorio temp si existe
        $tempPath = "features/temp";
        if ($disk->exists($tempPath)) {
            $this->info("Limpiando directorio temporal...");
            $tempFiles = $disk->allFiles($tempPath);
            
            foreach ($tempFiles as $file) {
                $fileSize = $disk->size($file);
                $totalSize += $fileSize;
                
                if ($dryRun) {
                    $this->line("  [DRY-RUN] Eliminaría: {$file} (" . $this->formatBytes($fileSize) . ")");
                } else {
                    if ($disk->delete($file)) {
                        $this->line("  ✓ Eliminado: {$file} (" . $this->formatBytes($fileSize) . ")");
                        $totalDeleted++;
                    }
                }
            }
            
            if (!$dryRun) {
                $this->cleanupEmptyDirectories($disk, $tempPath);
            }
        }

        $this->newLine();
        if ($dryRun) {
            $this->info("🔍 DRY-RUN completado. Se eliminarían {$totalDeleted} archivos (" . $this->formatBytes($totalSize) . ")");
        } else {
            $this->info("✅ Limpieza completada. Eliminados {$totalDeleted} archivos (" . $this->formatBytes($totalSize) . ")");
        }

        return Command::SUCCESS;
    }

    /**
     * Convierte una URL pública a ruta relativa
     *
     * @param string $url
     * @return string|null
     */
    private function urlToRelativePath(string $url): ?string
    {
        // Remover dominio y /storage/
        $url = str_replace(config('app.url'), '', $url);
        $url = ltrim($url, '/');
        
        if (Str::startsWith($url, 'storage/')) {
            return Str::after($url, 'storage/');
        }
        
        return null;
    }

    /**
     * Elimina directorios vacíos recursivamente
     *
     * @param \Illuminate\Contracts\Filesystem\Filesystem $disk
     * @param string $directory
     * @return void
     */
    private function cleanupEmptyDirectories($disk, string $directory): void
    {
        // Obtener subdirectorios
        $subdirs = $disk->directories($directory);
        
        // Limpiar subdirectorios primero
        foreach ($subdirs as $subdir) {
            $this->cleanupEmptyDirectories($disk, $subdir);
        }
        
        // Verificar si el directorio está vacío
        $files = $disk->files($directory);
        $dirs = $disk->directories($directory);
        
        if (empty($files) && empty($dirs)) {
            $disk->deleteDirectory($directory);
            $this->line("  ✓ Directorio vacío eliminado: {$directory}");
        }
    }

    /**
     * Formatea bytes a formato legible
     *
     * @param int $bytes
     * @return string
     */
    private function formatBytes(int $bytes): string
    {
        $units = ['B', 'KB', 'MB', 'GB'];
        $bytes = max($bytes, 0);
        $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
        $pow = min($pow, count($units) - 1);
        $bytes /= pow(1024, $pow);
        
        return round($bytes, 2) . ' ' . $units[$pow];
    }
}
