<?php
declare(strict_types=1);

namespace App\Framework\Logging;

use App\Framework\Attributes\Singleton;
use App\Framework\Logging\Handlers\ConsoleHandler;
use DateTimeZone;

/**
 * Einfacher Logger für das Framework.
 */
#[Singleton]
final readonly class DefaultLogger implements Logger
{
    /**
     * @param LogLevel $minLevel Minimales Level, das geloggt werden soll
     * @param array<LogHandler> $handlers Array von Log-Handlern
     * @param ProcessorManager $processorManager Optional: Processor Manager für die Verarbeitung
     */
    public function __construct(
        private LogLevel         $minLevel = LogLevel::DEBUG,
        /** @var LogHandler[] */
        private array            $handlers = [],
        private ProcessorManager $processorManager = new ProcessorManager(),
    ) {}

    public function debug(string $message, array $context = []): void
    {
        $this->log(LogLevel::DEBUG, $message, $context);
    }

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

    public function notice(string $message, array $context = []): void
    {
        $this->log(LogLevel::NOTICE, $message, $context);
    }

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

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

    public function critical(string $message, array $context = []): void
    {
        $this->log(LogLevel::CRITICAL, $message, $context);
    }

    public function alert(string $message, array $context = []): void
    {
        $this->log(LogLevel::ALERT, $message, $context);
    }

    public function emergency(string $message, array $context = []): void
    {
        $this->log(LogLevel::EMERGENCY, $message, $context);
    }

    /**
     * Log-Nachricht mit beliebigem Level erstellen
     *
     * @param LogLevel $level Log-Level
     * @param string $message Log-Nachricht
     * @param array $context Kontext-Daten für Platzhalter-Ersetzung
     */
    public function log(LogLevel $level, string $message, array $context = []): void
    {
        // Log-Record erstellen
        $record = new LogRecord(
            message: $message,
            context: $context,
            level: $level,
            timestamp: new \DateTimeImmutable(timezone: new DateTimeZone('Europe/Berlin')),
        );

        // Record durch alle Processors verarbeiten
        $processedRecord = $this->processorManager->processRecord($record);

        // Alle Handler durchlaufen
        foreach ($this->handlers as $handler) {
            if ($handler->isHandling($processedRecord)) {
                $handler->handle($processedRecord);
            }
        }
    }

    /**
     * Gibt die aktuelle Konfiguration des Loggers zurück
     */
    public function getConfiguration(): array
    {
        return [
            'minLevel' => $this->minLevel->value,
            'handlers' => array_map(fn(LogHandler $h) => get_class($h), $this->handlers),
            'processors' => $this->processorManager->getProcessorList(),
        ];
    }
}
