<?php

class SecurityLogger {
    private static $logPath = __DIR__ . '/../../logs/';
    private static $maxLogSize = 10 * 1024 * 1024; // 10MB
    private static $maxLogFiles = 5;
    
    /**
     * Inicializar sistema de logs
     */
    public static function init() {
        // Crear directorio de logs si no existe
        if (!is_dir(self::$logPath)) {
            mkdir(self::$logPath, 0750, true);
        }
        
        // Crear archivo .htaccess para proteger logs
        $htaccessPath = self::$logPath . '.htaccess';
        if (!file_exists($htaccessPath)) {
            file_put_contents($htaccessPath, "Require all denied\n");
        }
    }
    
    /**
     * Log de acceso a archivos
     */
    public static function logFileAccess($action, $fileName, $userId = null, $userRole = null, $success = true, $details = []) {
        $logData = [
            'timestamp' => date('Y-m-d H:i:s'),
            'type' => 'FILE_ACCESS',
            'action' => $action, // 'upload', 'download', 'delete', 'view'
            'file_name' => $fileName,
            'user_id' => $userId,
            'user_role' => $userRole,
            'ip_address' => self::getClientIP(),
            'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown',
            'success' => $success,
            'details' => $details
        ];
        
        self::writeLog('file_access', $logData);
    }
    
    /**
     * Log de intentos de autenticación
     */
    public static function logAuthAttempt($email, $success = true, $reason = null) {
        $logData = [
            'timestamp' => date('Y-m-d H:i:s'),
            'type' => 'AUTH_ATTEMPT',
            'email' => $email,
            'success' => $success,
            'reason' => $reason,
            'ip_address' => self::getClientIP(),
            'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown'
        ];
        
        self::writeLog('auth', $logData);
    }
    
    /**
     * Log de violaciones de seguridad
     */
    public static function logSecurityViolation($type, $description, $userId = null, $severity = 'medium') {
        $logData = [
            'timestamp' => date('Y-m-d H:i:s'),
            'type' => 'SECURITY_VIOLATION',
            'violation_type' => $type, // 'unauthorized_access', 'invalid_file', 'suspicious_activity'
            'description' => $description,
            'user_id' => $userId,
            'severity' => $severity, // 'low', 'medium', 'high', 'critical'
            'ip_address' => self::getClientIP(),
            'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown',
            'request_uri' => $_SERVER['REQUEST_URI'] ?? '',
            'request_method' => $_SERVER['REQUEST_METHOD'] ?? ''
        ];
        
        self::writeLog('security', $logData);
        
        // Para violaciones críticas, también log en error_log del sistema
        if ($severity === 'critical') {
            error_log("CRITICAL SECURITY VIOLATION: $description - IP: " . self::getClientIP());
        }
    }
    
    /**
     * Log de errores del sistema
     */
    public static function logSystemError($error, $context = []) {
        $logData = [
            'timestamp' => date('Y-m-d H:i:s'),
            'type' => 'SYSTEM_ERROR',
            'error' => $error,
            'context' => $context,
            'ip_address' => self::getClientIP(),
            'request_uri' => $_SERVER['REQUEST_URI'] ?? '',
            'request_method' => $_SERVER['REQUEST_METHOD'] ?? ''
        ];
        
        self::writeLog('system', $logData);
    }
    
    /**
     * Escribir log a archivo
     */
    private static function writeLog($logType, $data) {
        try {
            self::init();
            
            $fileName = self::$logPath . $logType . '_' . date('Y-m-d') . '.log';
            
            // Rotar log si es muy grande
            if (file_exists($fileName) && filesize($fileName) > self::$maxLogSize) {
                self::rotateLog($logType);
            }
            
            $logLine = json_encode($data) . "\n";
            file_put_contents($fileName, $logLine, FILE_APPEND | LOCK_EX);
            
        } catch (Exception $e) {
            // Si falla el logging, al menos intentar log en error_log del sistema
            error_log("Failed to write security log: " . $e->getMessage());
        }
    }
    
    /**
     * Rotar archivos de log
     */
    private static function rotateLog($logType) {
        $baseFileName = self::$logPath . $logType . '_' . date('Y-m-d');
        
        // Mover archivos existentes
        for ($i = self::$maxLogFiles - 1; $i >= 1; $i--) {
            $oldFile = $baseFileName . '.' . $i . '.log';
            $newFile = $baseFileName . '.' . ($i + 1) . '.log';
            
            if (file_exists($oldFile)) {
                if ($i + 1 > self::$maxLogFiles) {
                    unlink($oldFile); // Eliminar archivo más antiguo
                } else {
                    rename($oldFile, $newFile);
                }
            }
        }
        
        // Mover archivo actual
        $currentFile = $baseFileName . '.log';
        $rotatedFile = $baseFileName . '.1.log';
        
        if (file_exists($currentFile)) {
            rename($currentFile, $rotatedFile);
        }
    }
    
    /**
     * Obtener IP real del cliente
     */
    private static function getClientIP() {
        $ipKeys = ['HTTP_X_FORWARDED_FOR', 'HTTP_X_REAL_IP', 'HTTP_CLIENT_IP', 'REMOTE_ADDR'];
        
        foreach ($ipKeys as $key) {
            if (!empty($_SERVER[$key])) {
                $ips = explode(',', $_SERVER[$key]);
                $ip = trim($ips[0]);
                
                if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
                    return $ip;
                }
            }
        }
        
        return $_SERVER['REMOTE_ADDR'] ?? 'Unknown';
    }
    
    /**
     * Obtener estadísticas de logs de seguridad
     */
    public static function getSecurityStats($days = 7) {
        $stats = [
            'auth_attempts' => 0,
            'failed_auth' => 0,
            'file_accesses' => 0,
            'security_violations' => 0,
            'unique_ips' => [],
            'top_violations' => []
        ];
        
        try {
            for ($i = 0; $i < $days; $i++) {
                $date = date('Y-m-d', strtotime("-$i days"));
                
                // Procesar logs de autenticación
                $authFile = self::$logPath . 'auth_' . $date . '.log';
                if (file_exists($authFile)) {
                    $lines = file($authFile, FILE_IGNORE_NEW_LINES);
                    foreach ($lines as $line) {
                        $data = json_decode($line, true);
                        if ($data) {
                            $stats['auth_attempts']++;
                            if (!$data['success']) {
                                $stats['failed_auth']++;
                            }
                            $stats['unique_ips'][] = $data['ip_address'];
                        }
                    }
                }
                
                // Procesar logs de archivos
                $fileFile = self::$logPath . 'file_access_' . $date . '.log';
                if (file_exists($fileFile)) {
                    $lines = file($fileFile, FILE_IGNORE_NEW_LINES);
                    $stats['file_accesses'] += count($lines);
                }
                
                // Procesar logs de seguridad
                $securityFile = self::$logPath . 'security_' . $date . '.log';
                if (file_exists($securityFile)) {
                    $lines = file($securityFile, FILE_IGNORE_NEW_LINES);
                    foreach ($lines as $line) {
                        $data = json_decode($line, true);
                        if ($data) {
                            $stats['security_violations']++;
                            $violationType = $data['violation_type'] ?? 'unknown';
                            $stats['top_violations'][$violationType] = ($stats['top_violations'][$violationType] ?? 0) + 1;
                        }
                    }
                }
            }
            
            $stats['unique_ips'] = array_unique($stats['unique_ips']);
            arsort($stats['top_violations']);
            
        } catch (Exception $e) {
            error_log("Error getting security stats: " . $e->getMessage());
        }
        
        return $stats;
    }
    
    /**
     * Limpiar logs antiguos
     */
    public static function cleanOldLogs($daysToKeep = 30) {
        try {
            $cutoffDate = strtotime("-$daysToKeep days");
            $files = glob(self::$logPath . '*.log*');
            
            foreach ($files as $file) {
                if (filemtime($file) < $cutoffDate) {
                    unlink($file);
                }
            }
            
        } catch (Exception $e) {
            error_log("Error cleaning old logs: " . $e->getMessage());
        }
    }
}