<?php

/**
 * Sistema de Logging para GGEE
 * Registra actividades del sistema con diferentes niveles de severidad
 */
class SystemLogger
{
    private static $instance = null;
    private $logFile;
    private $maxFileSize = 5242880; // 5MB
    private $maxFiles = 5;

    private function __construct()
    {
        $this->logFile = __DIR__ . '/../logs/app.log';
        $this->ensureLogDirectory();
    }

    public static function getInstance()
    {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    private function ensureLogDirectory()
    {
        $logDir = dirname($this->logFile);
        if (!is_dir($logDir)) {
            mkdir($logDir, 0755, true);
        }
    }

    /**
     * Rotar archivos de log cuando alcanzan el tamaño máximo
     */
    private function rotateLogIfNeeded()
    {
        if (!file_exists($this->logFile)) {
            return;
        }

        if (filesize($this->logFile) > $this->maxFileSize) {
            // Mover logs antiguos
            for ($i = $this->maxFiles - 1; $i > 0; $i--) {
                $oldFile = $this->logFile . '.' . $i;
                $newFile = $this->logFile . '.' . ($i + 1);
                if (file_exists($oldFile)) {
                    rename($oldFile, $newFile);
                }
            }

            // Mover el archivo actual
            rename($this->logFile, $this->logFile . '.1');
        }
    }

    /**
     * Escribir entrada al log
     */
    private function writeLog($level, $action, $details = '', $userId = null)
    {
        $this->rotateLogIfNeeded();

        $timestamp = date('Y-m-d H:i:s');
        $user = $userId ?? ($_SESSION['user_id'] ?? 'Sistema');
        $userName = $_SESSION['nombre'] ?? 'Usuario Desconocido';
        $userRole = $_SESSION['rol'] ?? 'N/A';
        $ip = $_SERVER['REMOTE_ADDR'] ?? 'N/A';

        // Si los detalles son array, convertir a JSON
        if (is_array($details)) {
            $details = json_encode($details, JSON_UNESCAPED_UNICODE);
        }

        $logEntry = sprintf(
            "[%s] [%s] [User: %s (%s)] [Role: %s] [IP: %s] [Action: %s] [Details: %s]" . PHP_EOL,
            $timestamp,
            $level,
            $user,
            $userName,
            $userRole,
            $ip,
            $action,
            $details
        );

        file_put_contents($this->logFile, $logEntry, FILE_APPEND | LOCK_EX);
    }

    /**
     * Registrar actividad de información
     */
    public function info($action, $details = '')
    {
        $this->writeLog('INFO', $action, $details);
    }

    /**
     * Registrar actividad de advertencia
     */
    public function warning($action, $details = '')
    {
        $this->writeLog('WARNING', $action, $details);
    }

    /**
     * Registrar actividad de error
     */
    public function error($action, $details = '')
    {
        $this->writeLog('ERROR', $action, $details);
    }

    /**
     * Registrar actividades críticas del sistema
     */
    public function critical($action, $details = '')
    {
        $this->writeLog('CRITICAL', $action, $details);
    }

    /**
     * Registrar actividades de acceso y autenticación
     */
    public function auth($action, $details = '')
    {
        $this->writeLog('AUTH', $action, $details);
    }

    /**
     * Registrar actividades relacionadas con datos
     */
    public function data($action, $details = '')
    {
        $this->writeLog('DATA', $action, $details);
    }

    /**
     * Registrar información de depuración (debugging)
     */
    public function debug($action, $details = '')
    {
        $this->writeLog('DEBUG', $action, $details);
    }

    /**
     * Obtener logs con filtros
     */
    public function getLogs($limit = 1000, $level = null, $startDate = null, $endDate = null)
    {
        if (!file_exists($this->logFile)) {
            return [];
        }

        $logs = file($this->logFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
        if (!$logs) {
            return [];
        }

        $logs = array_reverse($logs); // Más recientes primero
        $filteredLogs = [];

        foreach ($logs as $log) {
            // Parsear la línea del log
            if (preg_match('/\[(.*?)\] \[(.*?)\] \[User: (.*?)\] \[Role: (.*?)\] \[IP: (.*?)\] \[Action: (.*?)\] \[Details: (.*?)\]/', $log, $matches)) {
                $logData = [
                    'timestamp' => $matches[1],
                    'level' => $matches[2],
                    'user' => $matches[3],
                    'role' => $matches[4],
                    'ip' => $matches[5],
                    'action' => $matches[6],
                    'details' => $matches[7],
                    'raw' => $log
                ];

                // Aplicar filtros
                if ($level && $logData['level'] !== $level) {
                    continue;
                }

                if ($startDate && strtotime($logData['timestamp']) < strtotime($startDate)) {
                    continue;
                }

                if ($endDate && strtotime($logData['timestamp']) > strtotime($endDate . ' 23:59:59')) {
                    continue;
                }

                $filteredLogs[] = $logData;

                if (count($filteredLogs) >= $limit) {
                    break;
                }
            }
        }

        return $filteredLogs;
    }

    /**
     * Obtener estadísticas de logs
     */
    public function getStats()
    {
        $logs = $this->getLogs(10000); // Últimos 10k registros
        $stats = [
            'total' => count($logs),
            'levels' => [],
            'actions' => [],
            'users' => [],
            'today' => 0,
            'week' => 0
        ];

        $today = date('Y-m-d');
        $weekAgo = date('Y-m-d', strtotime('-7 days'));

        foreach ($logs as $log) {
            // Contar por nivel
            $level = $log['level'];
            $stats['levels'][$level] = ($stats['levels'][$level] ?? 0) + 1;

            // Contar por acción
            $action = $log['action'];
            $stats['actions'][$action] = ($stats['actions'][$action] ?? 0) + 1;

            // Contar por usuario
            $user = $log['user'];
            $stats['users'][$user] = ($stats['users'][$user] ?? 0) + 1;

            // Contar por fecha
            $logDate = date('Y-m-d', strtotime($log['timestamp']));
            if ($logDate === $today) {
                $stats['today']++;
            }
            if ($logDate >= $weekAgo) {
                $stats['week']++;
            }
        }

        return $stats;
    }
}

/**
 * Función helper para acceso rápido al logger
 */
function log_activity($action, $details = '', $level = 'info')
{
    $logger = SystemLogger::getInstance();

    switch (strtolower($level)) {
        case 'warning':
            $logger->warning($action, $details);
            break;
        case 'error':
            $logger->error($action, $details);
            break;
        case 'critical':
            $logger->critical($action, $details);
            break;
        case 'auth':
            $logger->auth($action, $details);
            break;
        case 'data':
            $logger->data($action, $details);
            break;
        default:
            $logger->info($action, $details);
    }
}
