<?php

/**
 * Logger Service
 * Provides structured logging functionality
 */
class Logger {
    
    const LEVEL_DEBUG = 'DEBUG';
    const LEVEL_INFO = 'INFO';
    const LEVEL_WARNING = 'WARNING';
    const LEVEL_ERROR = 'ERROR';
    const LEVEL_CRITICAL = 'CRITICAL';
    
    private static $logFile;
    private static $authLogFile;
    private static $dbLogFile;
    private static $fileLogFile;
    
    /**
     * Initialize logger
     */
    public static function init() {
        self::$logFile = LOG_PATH . '/app.log';
        self::$authLogFile = LOG_PATH . '/auth.log';
        self::$dbLogFile = LOG_PATH . '/database.log';
        self::$fileLogFile = LOG_PATH . '/file_operations.log';
        
        // Ensure log files exist
        self::ensureLogFile(self::$logFile);
        self::ensureLogFile(self::$authLogFile);
        self::ensureLogFile(self::$dbLogFile);
        self::ensureLogFile(self::$fileLogFile);
    }
    
    /**
     * Ensure log file exists
     * 
     * @param string $file
     */
    private static function ensureLogFile($file) {
        if (!file_exists($file)) {
            touch($file);
            chmod($file, 0644);
        }
    }
    
    /**
     * Log debug message
     * 
     * @param string $message
     * @param array $context
     */
    public static function debug($message, $context = []) {
        self::log(self::LEVEL_DEBUG, $message, $context);
    }
    
    /**
     * Log info message
     * 
     * @param string $message
     * @param array $context
     */
    public static function info($message, $context = []) {
        self::log(self::LEVEL_INFO, $message, $context);
    }
    
    /**
     * Log warning message
     * 
     * @param string $message
     * @param array $context
     */
    public static function warning($message, $context = []) {
        self::log(self::LEVEL_WARNING, $message, $context);
    }
    
    /**
     * Log error message
     * 
     * @param string $message
     * @param array $context
     */
    public static function error($message, $context = []) {
        self::log(self::LEVEL_ERROR, $message, $context);
    }
    
    /**
     * Log critical message
     * 
     * @param string $message
     * @param array $context
     */
    public static function critical($message, $context = []) {
        self::log(self::LEVEL_CRITICAL, $message, $context);
    }
    
    /**
     * Log authentication attempt
     * 
     * @param string $username
     * @param bool $success
     * @param string $ip
     */
    public static function logAuth($username, $success, $ip = null) {
        $ip = $ip ?? ($_SERVER['REMOTE_ADDR'] ?? 'unknown');
        $status = $success ? 'SUCCESS' : 'FAILED';
        
        $message = sprintf(
            "[%s] %s: Login attempt for user '%s' from IP %s",
            date('Y-m-d H:i:s'),
            $status,
            $username,
            $ip
        );
        
        self::writeToFile(self::$authLogFile, $message);
    }
    
    /**
     * Log database query
     * 
     * @param string $query
     * @param array $params
     * @param float $executionTime
     * @param bool $success
     */
    public static function logDatabase($query, $params = [], $executionTime = 0, $success = true) {
        $status = $success ? 'SUCCESS' : 'FAILED';
        
        $message = sprintf(
            "[%s] %s: Query executed in %.4f seconds\nQuery: %s\nParams: %s",
            date('Y-m-d H:i:s'),
            $status,
            $executionTime,
            $query,
            json_encode($params)
        );
        
        self::writeToFile(self::$dbLogFile, $message);
    }
    
    /**
     * Log file operation
     * 
     * @param string $operation Operation type (upload, delete, etc.)
     * @param string $filename
     * @param bool $success
     * @param string $error Optional error message
     */
    public static function logFileOperation($operation, $filename, $success, $error = null) {
        $status = $success ? 'SUCCESS' : 'FAILED';
        
        $message = sprintf(
            "[%s] %s: %s operation on file '%s'",
            date('Y-m-d H:i:s'),
            $status,
            strtoupper($operation),
            $filename
        );
        
        if ($error) {
            $message .= "\nError: " . $error;
        }
        
        self::writeToFile(self::$fileLogFile, $message);
    }
    
    /**
     * Main log method
     * 
     * @param string $level
     * @param string $message
     * @param array $context
     */
    private static function log($level, $message, $context = []) {
        $logMessage = sprintf(
            "[%s] [%s] %s",
            date('Y-m-d H:i:s'),
            $level,
            $message
        );
        
        if (!empty($context)) {
            $logMessage .= "\nContext: " . json_encode($context, JSON_PRETTY_PRINT);
        }
        
        // Add request info for errors and critical
        if (in_array($level, [self::LEVEL_ERROR, self::LEVEL_CRITICAL])) {
            $logMessage .= "\nRequest: " . ($_SERVER['REQUEST_METHOD'] ?? 'CLI') . ' ' . ($_SERVER['REQUEST_URI'] ?? 'N/A');
            $logMessage .= "\nUser: " . (isset($_SESSION['user_id']) ? $_SESSION['user_id'] : 'Guest');
            $logMessage .= "\nIP: " . ($_SERVER['REMOTE_ADDR'] ?? 'unknown');
        }
        
        self::writeToFile(self::$logFile, $logMessage);
    }
    
    /**
     * Write message to log file
     * 
     * @param string $file
     * @param string $message
     */
    private static function writeToFile($file, $message) {
        if (!$file) {
            self::init();
        }
        
        error_log($message . "\n\n", 3, $file);
    }
    
    /**
     * Get log file contents
     * 
     * @param string $type Log type (app, auth, database, file)
     * @param int $lines Number of lines to retrieve
     * @return array
     */
    public static function getLogContents($type = 'app', $lines = 100) {
        $files = [
            'app' => self::$logFile,
            'auth' => self::$authLogFile,
            'database' => self::$dbLogFile,
            'file' => self::$fileLogFile
        ];
        
        $file = $files[$type] ?? self::$logFile;
        
        if (!file_exists($file)) {
            return [];
        }
        
        // Read last N lines
        $content = file($file);
        return array_slice($content, -$lines);
    }
    
    /**
     * Clear log file
     * 
     * @param string $type Log type
     * @return bool
     */
    public static function clearLog($type = 'app') {
        $files = [
            'app' => self::$logFile,
            'auth' => self::$authLogFile,
            'database' => self::$dbLogFile,
            'file' => self::$fileLogFile
        ];
        
        $file = $files[$type] ?? self::$logFile;
        
        if (file_exists($file)) {
            return file_put_contents($file, '') !== false;
        }
        
        return false;
    }
    
    /**
     * Rotate log files (keep last N days)
     * 
     * @param int $days
     */
    public static function rotateLogs($days = 30) {
        $files = [
            self::$logFile,
            self::$authLogFile,
            self::$dbLogFile,
            self::$fileLogFile
        ];
        
        foreach ($files as $file) {
            if (!file_exists($file)) {
                continue;
            }
            
            // Check file age
            $fileAge = time() - filemtime($file);
            $maxAge = $days * 24 * 60 * 60;
            
            if ($fileAge > $maxAge) {
                // Archive old log
                $archiveName = $file . '.' . date('Y-m-d', filemtime($file)) . '.old';
                rename($file, $archiveName);
                
                // Create new log file
                touch($file);
                chmod($file, 0644);
            }
        }
    }
}

// Initialize logger
Logger::init();
