<?php
/**
 * Bundled minimal implementation of monolog/monolog 3.x — Logger.
 *
 * Implements the surface BlackRed uses:
 *   - new Logger($channel)
 *   - pushHandler() / pushProcessor()
 *   - debug() / info() / notice() / warning() / error() / critical() / alert() / emergency()
 *
 * Original library: https://github.com/Seldaek/monolog (MIT)
 */

declare(strict_types=1);

namespace Monolog;

use Monolog\Handler\HandlerInterface;

final class Logger
{
    /** @var list<HandlerInterface> */
    private array $handlers = [];

    /** @var list<callable> */
    private array $processors = [];

    public function __construct(private readonly string $name)
    {
    }

    public function pushHandler(HandlerInterface $handler): self
    {
        array_unshift($this->handlers, $handler);
        return $this;
    }

    public function pushProcessor(callable $processor): self
    {
        array_unshift($this->processors, $processor);
        return $this;
    }

    public function debug(string $message, array $context = []): void
    {
        $this->addRecord(Level::Debug, $message, $context);
    }

    public function info(string $message, array $context = []): void
    {
        $this->addRecord(Level::Info, $message, $context);
    }

    public function notice(string $message, array $context = []): void
    {
        $this->addRecord(Level::Notice, $message, $context);
    }

    public function warning(string $message, array $context = []): void
    {
        $this->addRecord(Level::Warning, $message, $context);
    }

    public function error(string $message, array $context = []): void
    {
        $this->addRecord(Level::Error, $message, $context);
    }

    public function critical(string $message, array $context = []): void
    {
        $this->addRecord(Level::Critical, $message, $context);
    }

    public function alert(string $message, array $context = []): void
    {
        $this->addRecord(Level::Alert, $message, $context);
    }

    public function emergency(string $message, array $context = []): void
    {
        $this->addRecord(Level::Emergency, $message, $context);
    }

    private function addRecord(Level $level, string $message, array $context): void
    {
        $record = [
            'channel'    => $this->name,
            'level'      => $level->value,
            'level_name' => $level->getName(),
            'message'    => $message,
            'context'    => $context,
            'datetime'   => date('c'),
        ];

        foreach ($this->processors as $processor) {
            $record = $processor($record);
        }

        foreach ($this->handlers as $handler) {
            $handler->handle($record);
        }
    }
}
