<?php
/**
 * Script de Limpieza de Logs
 * Sistema de Inventario Forestal de Guatemala
 * 
 * Este script limpia logs antiguos y archivos temporales
 * para mantener el sistema optimizado
 */

require_once __DIR__ . '/../api/config/environment.php';

class LogCleanup {
    private $logDir;
    private $maxLogAge;
    private $maxLogSize;
    private $maxLogFiles;
    
    public function __construct() {
        $this->logDir = __DIR__ . '/../logs/';
        $this->maxLogAge = Environment::get('LOG_MAX_AGE_DAYS', 30) * 24 * 60 * 60; // 30 días por defecto
        $this->maxLogSize = Environment::get('LOG_MAX_SIZE', 10485760); // 10MB por defecto
        $this->maxLogFiles = Environment::get('LOG_MAX_FILES', 10); // 10 archivos por defecto
    }
    
    /**
     * Ejecutar limpieza completa
     */
    public function runCleanup() {
        $results = [
            'timestamp' => date('Y-m-d H:i:s'),
            'actions' => [],
            'stats' => [
                'files_deleted' => 0,
                'files_rotated' => 0,
                'space_freed' => 0
            ]
        ];
        
        // Crear directorio de logs si no existe
        if (!is_dir($this->logDir)) {
            mkdir($this->logDir, 0755, true);
            $results['actions'][] = 'Directorio de logs creado';
        }
        
        // Limpiar logs antiguos
        $this->cleanOldLogs($results);
        
        // Rotar logs grandes
        $this->rotateLargeLogs($results);
        
        // Limpiar archivos temporales
        $this->cleanTempFiles($results);
        
        // Limpiar cache si existe
        $this->cleanCache($results);
        
        // Comprimir logs antiguos
        $this->compressOldLogs($results);
        
        // Registrar actividad
        $this->logCleanupActivity($results);
        
        return $results;
    }
    
    /**
     * Limpiar logs antiguos
     */
    private function cleanOldLogs(&$results) {
        $logFiles = glob($this->logDir . '*.log');
        $cutoffTime = time() - $this->maxLogAge;
        
        foreach ($logFiles as $logFile) {
            if (filemtime($logFile) < $cutoffTime) {
                $size = filesize($logFile);
                if (unlink($logFile)) {
                    $results['actions'][] = 'Log antiguo eliminado: ' . basename($logFile);
                    $results['stats']['files_deleted']++;
                    $results['stats']['space_freed'] += $size;
                }
            }
        }
    }
    
    /**
     * Rotar logs grandes
     */
    private function rotateLargeLogs(&$results) {
        $logFiles = glob($this->logDir . '*.log');
        
        foreach ($logFiles as $logFile) {
            if (filesize($logFile) > $this->maxLogSize) {
                $this->rotateLogFile($logFile, $results);
            }
        }
    }
    
    /**
     * Rotar un archivo de log específico
     */
    private function rotateLogFile($logFile, &$results) {
        $baseName = pathinfo($logFile, PATHINFO_FILENAME);
        $timestamp = date('Y-m-d_H-i-s');
        $rotatedFile = $this->logDir . $baseName . '_' . $timestamp . '.log';
        
        // Mover archivo actual
        if (rename($logFile, $rotatedFile)) {
            // Crear nuevo archivo vacío
            touch($logFile);
            chmod($logFile, 0644);
            
            $results['actions'][] = 'Log rotado: ' . basename($logFile) . ' -> ' . basename($rotatedFile);
            $results['stats']['files_rotated']++;
            
            // Comprimir archivo rotado
            $this->compressFile($rotatedFile);
        }
    }
    
    /**
     * Limpiar archivos temporales
     */
    private function cleanTempFiles(&$results) {
        $tempDirs = [
            sys_get_temp_dir(),
            __DIR__ . '/../temp/',
            __DIR__ . '/../cache/temp/'
        ];
        
        foreach ($tempDirs as $tempDir) {
            if (is_dir($tempDir)) {
                $this->cleanTempDirectory($tempDir, $results);
            }
        }
    }
    
    /**
     * Limpiar directorio temporal
     */
    private function cleanTempDirectory($dir, &$results) {
        $files = glob($dir . '/sif_gt_*');
        $cutoffTime = time() - (24 * 60 * 60); // 24 horas
        
        foreach ($files as $file) {
            if (filemtime($file) < $cutoffTime) {
                $size = is_file($file) ? filesize($file) : 0;
                
                if (is_file($file)) {
                    if (unlink($file)) {
                        $results['actions'][] = 'Archivo temporal eliminado: ' . basename($file);
                        $results['stats']['files_deleted']++;
                        $results['stats']['space_freed'] += $size;
                    }
                } elseif (is_dir($file)) {
                    if ($this->removeDirectory($file)) {
                        $results['actions'][] = 'Directorio temporal eliminado: ' . basename($file);
                        $results['stats']['files_deleted']++;
                    }
                }
            }
        }
    }
    
    /**
     * Limpiar cache
     */
    private function cleanCache(&$results) {
        $cacheDir = __DIR__ . '/../cache/';
        
        if (!is_dir($cacheDir)) {
            return;
        }
        
        $cacheFiles = glob($cacheDir . '*');
        $cutoffTime = time() - Environment::get('CACHE_TTL', 3600);
        
        foreach ($cacheFiles as $cacheFile) {
            if (is_file($cacheFile) && filemtime($cacheFile) < $cutoffTime) {
                $size = filesize($cacheFile);
                if (unlink($cacheFile)) {
                    $results['actions'][] = 'Cache eliminado: ' . basename($cacheFile);
                    $results['stats']['files_deleted']++;
                    $results['stats']['space_freed'] += $size;
                }
            }
        }
    }
    
    /**
     * Comprimir logs antiguos
     */
    private function compressOldLogs(&$results) {
        $logFiles = glob($this->logDir . '*.log');
        $compressAge = 7 * 24 * 60 * 60; // 7 días
        $cutoffTime = time() - $compressAge;
        
        foreach ($logFiles as $logFile) {
            // No comprimir logs activos
            if (in_array(basename($logFile), ['system.log', 'error.log', 'access.log'])) {
                continue;
            }
            
            if (filemtime($logFile) < $cutoffTime && pathinfo($logFile, PATHINFO_EXTENSION) === 'log') {
                if ($this->compressFile($logFile)) {
                    $results['actions'][] = 'Log comprimido: ' . basename($logFile);
                }
            }
        }
    }
    
    /**
     * Comprimir archivo
     */
    private function compressFile($filePath) {
        if (!file_exists($filePath)) {
            return false;
        }
        
        $compressedPath = $filePath . '.gz';
        
        $file = fopen($filePath, 'rb');
        $compressed = gzopen($compressedPath, 'wb9');
        
        if (!$file || !$compressed) {
            return false;
        }
        
        while (!feof($file)) {
            gzwrite($compressed, fread($file, 1024 * 512));
        }
        
        fclose($file);
        gzclose($compressed);
        
        // Eliminar archivo original si la compresión fue exitosa
        if (file_exists($compressedPath) && filesize($compressedPath) > 0) {
            unlink($filePath);
            return true;
        }
        
        return false;
    }
    
    /**
     * Remover directorio recursivamente
     */
    private function removeDirectory($dir) {
        if (!is_dir($dir)) {
            return false;
        }
        
        $files = array_diff(scandir($dir), array('.', '..'));
        
        foreach ($files as $file) {
            $path = $dir . DIRECTORY_SEPARATOR . $file;
            if (is_dir($path)) {
                $this->removeDirectory($path);
            } else {
                unlink($path);
            }
        }
        
        return rmdir($dir);
    }
    
    /**
     * Registrar actividad de limpieza
     */
    private function logCleanupActivity($results) {
        $logFile = $this->logDir . 'cleanup.log';
        
        $logEntry = [
            'timestamp' => $results['timestamp'],
            'stats' => $results['stats'],
            'actions_count' => count($results['actions'])
        ];
        
        $logLine = json_encode($logEntry) . "\n";
        file_put_contents($logFile, $logLine, FILE_APPEND | LOCK_EX);
    }
    
    /**
     * Obtener estadísticas de logs
     */
    public function getLogStats() {
        $stats = [
            'total_files' => 0,
            'total_size' => 0,
            'by_type' => [],
            'oldest_file' => null,
            'newest_file' => null
        ];
        
        if (!is_dir($this->logDir)) {
            return $stats;
        }
        
        $files = glob($this->logDir . '*');
        $oldestTime = PHP_INT_MAX;
        $newestTime = 0;
        
        foreach ($files as $file) {
            if (is_file($file)) {
                $stats['total_files']++;
                $size = filesize($file);
                $stats['total_size'] += $size;
                
                $ext = pathinfo($file, PATHINFO_EXTENSION);
                if (!isset($stats['by_type'][$ext])) {
                    $stats['by_type'][$ext] = ['count' => 0, 'size' => 0];
                }
                $stats['by_type'][$ext]['count']++;
                $stats['by_type'][$ext]['size'] += $size;
                
                $mtime = filemtime($file);
                if ($mtime < $oldestTime) {
                    $oldestTime = $mtime;
                    $stats['oldest_file'] = [
                        'name' => basename($file),
                        'date' => date('Y-m-d H:i:s', $mtime)
                    ];
                }
                
                if ($mtime > $newestTime) {
                    $newestTime = $mtime;
                    $stats['newest_file'] = [
                        'name' => basename($file),
                        'date' => date('Y-m-d H:i:s', $mtime)
                    ];
                }
            }
        }
        
        // Formatear tamaños
        $stats['total_size_formatted'] = $this->formatBytes($stats['total_size']);
        foreach ($stats['by_type'] as &$type) {
            $type['size_formatted'] = $this->formatBytes($type['size']);
        }
        
        return $stats;
    }
    
    /**
     * Formatear bytes a formato legible
     */
    private function formatBytes($bytes, $precision = 2) {
        $units = array('B', 'KB', 'MB', 'GB', 'TB');
        
        for ($i = 0; $bytes > 1024 && $i < count($units) - 1; $i++) {
            $bytes /= 1024;
        }
        
        return round($bytes, $precision) . ' ' . $units[$i];
    }
}

// Ejecutar limpieza si se llama directamente
if (php_sapi_name() === 'cli' || (isset($_GET['action']) && $_GET['action'] === 'cleanup')) {
    $cleanup = new LogCleanup();
    
    if (isset($_GET['stats'])) {
        $stats = $cleanup->getLogStats();
        
        if (php_sapi_name() === 'cli') {
            echo "=== LOG STATISTICS ===\n";
            echo "Total archivos: " . $stats['total_files'] . "\n";
            echo "Tamaño total: " . $stats['total_size_formatted'] . "\n";
            
            if ($stats['oldest_file']) {
                echo "Archivo más antiguo: " . $stats['oldest_file']['name'] . " (" . $stats['oldest_file']['date'] . ")\n";
            }
            
            if ($stats['newest_file']) {
                echo "Archivo más reciente: " . $stats['newest_file']['name'] . " (" . $stats['newest_file']['date'] . ")\n";
            }
            
            echo "\nPor tipo:\n";
            foreach ($stats['by_type'] as $type => $data) {
                echo "  .{$type}: {$data['count']} archivos, {$data['size_formatted']}\n";
            }
            
            echo "=====================\n";
        } else {
            header('Content-Type: application/json');
            echo json_encode($stats, JSON_PRETTY_PRINT);
        }
    } else {
        $results = $cleanup->runCleanup();
        
        if (php_sapi_name() === 'cli') {
            echo "=== LOG CLEANUP REPORT ===\n";
            echo "Fecha: " . $results['timestamp'] . "\n";
            echo "Archivos eliminados: " . $results['stats']['files_deleted'] . "\n";
            echo "Archivos rotados: " . $results['stats']['files_rotated'] . "\n";
            echo "Espacio liberado: " . number_format($results['stats']['space_freed'] / 1024, 2) . " KB\n";
            
            echo "\nAcciones realizadas:\n";
            foreach ($results['actions'] as $action) {
                echo "  - {$action}\n";
            }
            
            echo "==========================\n";
        } else {
            header('Content-Type: application/json');
            echo json_encode($results, JSON_PRETTY_PRINT);
        }
    }
}
?>