<?php
/**
 * Logger - Application logging library
 * Supports INFO, WARNING, ERROR, DEBUG, TRACE levels.
 * Debug and Trace modes are controlled by settings.
 */

class Logger
{
    private static ?Logger $instance = null;

    private bool $debugMode = false;
    private bool $traceMode = false;

    private function __construct()
    {
        $this->ensureLogDir();
        $this->debugMode = defined('DEBUG_MODE') && DEBUG_MODE;
        $this->traceMode = defined('TRACE_MODE') && TRACE_MODE;
    }

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

    public function setDebugMode(bool $enabled): void
    {
        $this->debugMode = $enabled;
    }

    public function setTraceMode(bool $enabled): void
    {
        $this->traceMode = $enabled;
    }

    public function info(string $message, array $context = []): void
    {
        $this->write(LOG_APP_FILE, 'INFO', $message, $context);
    }

    public function warning(string $message, array $context = []): void
    {
        $this->write(LOG_APP_FILE, 'WARNING', $message, $context);
    }

    public function error(string $message, array $context = []): void
    {
        $this->write(LOG_APP_FILE, 'ERROR', $message, $context);
    }

    public function debug(string $message, array $context = []): void
    {
        if (!$this->debugMode) {
            return;
        }
        $this->write(LOG_DEBUG_FILE, 'DEBUG', $message, $context);
    }

    public function trace(string $message, array $context = []): void
    {
        if (!$this->traceMode) {
            return;
        }
        $this->write(LOG_TRACE_FILE, 'TRACE', $message, $context);
        // Also write a PHP backtrace
        $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5);
        $traceStr = '';
        foreach ($backtrace as $i => $frame) {
            $file = $frame['file'] ?? 'unknown';
            $line = $frame['line'] ?? 0;
            $func = ($frame['class'] ?? '') . ($frame['type'] ?? '') . ($frame['function'] ?? '');
            $traceStr .= "  #$i $file($line): $func()\n";
        }
        $this->write(LOG_TRACE_FILE, 'TRACE', "Backtrace:\n$traceStr", []);
    }

    private function write(string $file, string $level, string $message, array $context): void
    {
        $timestamp = date('Y-m-d H:i:s');
        $ip = $_SERVER['REMOTE_ADDR'] ?? 'cli';
        $user = isset($_SESSION['user_id']) ? 'uid:' . $_SESSION['user_id'] : 'guest';

        if (!empty($context)) {
            $contextStr = ' ' . json_encode($context, JSON_UNESCAPED_UNICODE);
        } else {
            $contextStr = '';
        }

        $line = "[$timestamp] [$level] [$ip] [$user] $message$contextStr\n";

        @file_put_contents($file, $line, FILE_APPEND | LOCK_EX);
    }

    private function ensureLogDir(): void
    {
        if (!defined('LOG_PATH')) {
            return;
        }
        if (!is_dir(LOG_PATH)) {
            @mkdir(LOG_PATH, 0750, true);
        }
    }
}
