<?php
/**
 * CloudXM SDK Logger Factory - Basic File-Only Logging
 *
 * Provides basic file logging infrastructure for plugins.
 * Enhanced logging features (Loki, database) are provided by the Logger plugin.
 */

namespace CloudXM\SDK\Utilities;

use Monolog\Logger;
use Monolog\Level;
use Monolog\Handler\RotatingFileHandler;
use Monolog\Handler\FilterHandler;
use Monolog\Formatter\LineFormatter;
use Monolog\Processor\PsrLogMessageProcessor;
use Monolog\Processor\WebProcessor;
use CloudXM\SDK\Utilities\CustomLineFormatter;
use CloudXM\SDK\Transport\ConditionalSinkHandler;
use CloudXM\SDK\Contracts\EventDispatcherInterface;
use CloudXM\SDK\Services\EventDispatcher;
use CloudXM\SDK\Config\Configuration;

class LoggerFactory
{
    private static ?Configuration $config = null;

    /**
     * Get a configured logger for the given channel.
     *
     * @param string $channel Logger channel name
     */
    public static function get(string $channel): Logger
    {
        return self::create($channel);
    }

    /**
     * Create a simple logger instance (alias for create).
     *
     * @param string $channel Logger channel name
     */
    public static function createSimple(string $channel): Logger
    {
        return self::create($channel);
    }

    /**
     * Create a basic logger instance with file-only logging.
     *
     * This provides basic WordPress debug.log compatible logging.
     * Enhanced features like Loki integration are handled by the Logger plugin.
     */
    public static function create(string $channel = 'cloudxm'): Logger
    {
        $config = self::getConfig();

        // Level from config
        $minLevelStr = (string) $config->get('logging.min_level', 'info');
        $level = Level::fromName(strtoupper($minLevelStr));

        // Formatter: custom formatter for pretty-printed JSON context
        $lineFormatter = new CustomLineFormatter(
            "[%datetime%] %level_name% [%channel%] %message%\n",
            "Y-m-d H:i:s",
            false, // allowInlineLineBreaks
            false  // include context/extra for stacktraces
        );

        // Create event dispatcher for decoupled filtering (plugins can hook into this)
        // Use global singleton so Logger plugin can listen to the same events
        if (isset($GLOBALS['cloudxm_sdk_event_dispatcher'])) {
            $eventDispatcher = $GLOBALS['cloudxm_sdk_event_dispatcher'];
        } else {
            $eventDispatcher = new EventDispatcher();
            $GLOBALS['cloudxm_sdk_event_dispatcher'] = $eventDispatcher;
        }

        // Enhanced handler with ConditionalSinkHandler for plugin extensibility
        $logFile = self::resolveLogFile();
        $fileHandler = new \Monolog\Handler\StreamHandler($logFile, $level, true, 0640);
        $fileHandler->setFormatter($lineFormatter);

        // Apply global log level filtering if set by Logger plugin
        if (defined('CLOUDXM_LOG_LEVEL')) {
            $fileHandler->setLevel(Level::fromName(strtoupper(CLOUDXM_LOG_LEVEL)));
        }

        // Use ConditionalSinkHandler for plugin-extensible logging
        $conditionalHandler = new ConditionalSinkHandler($fileHandler, 'internal', $eventDispatcher);

        try {
            $logger = new Logger($channel);
        } catch (\Throwable $e) {
            $logger = new Logger('fallback');
        }

        $logger->pushHandler($conditionalHandler);

        return $logger;
    }

    /**
     * Determine a writable log file path (fallbacks if WP constants are missing).
     */
    private static function resolveLogFile(): string
    {
        $base = defined('WP_CONTENT_DIR') ? WP_CONTENT_DIR : sys_get_temp_dir();
        $path = rtrim($base, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . 'debug.log';
        // Ensure directory exists
        $dir = dirname($path);
        if (!is_dir($dir)) {
            @mkdir($dir, 0755, true);
        }
        return $path;
    }

    /**
     * Lazy-load basic config
     */
    private static function getConfig(): Configuration
    {
        if (self::$config === null) {
            self::$config = Configuration::getInstance();
        }
        return self::$config;
    }
}