<?php
/**
 * Copyright since 2025 InPost S.A.
 *
 * For the full license information, please view the LICENSE file bundled with the module.
 *
 * @author InPost S.A.
 * @copyright since 2025 InPost S.A.
 * @license MIT
 */

declare(strict_types=1);

namespace InPost\International\Log\Handler;

use Monolog\Handler\HandlerInterface;
use Monolog\Logger;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;

if (!defined('_PS_VERSION_')) {
    exit;
}

abstract class AbstractHandlerFactory implements HandlerFactoryInterface
{
    /**
     * @var string
     */
    private $environment;

    /**
     * @var OptionsResolver|null
     */
    private $optionsResolver;

    public function __construct(string $environment = _PS_ENV_)
    {
        $this->environment = $environment;
    }

    /**
     * {@inheritDoc}
     */
    public function create(array $options): HandlerInterface
    {
        $options = $this->getOptionsResolver()->resolve($options);

        return $this->doCreate($options);
    }

    protected function createOptionsResolver(): OptionsResolver
    {
        return (new OptionsResolver())
            ->setDefaults([
                'level' => 'prod' === $this->environment ? Logger::INFO : Logger::DEBUG,
                'bubble' => true,
            ])
            ->setNormalizer('level', static function (Options $options, $value) {
                if (null === $value || is_numeric($value)) {
                    return $value;
                }

                $upper = strtoupper($value);
                $constName = sprintf('%s::%s', Logger::class, $upper);

                if (defined($constName)) {
                    return constant($constName);
                }

                throw new \DomainException(sprintf('Could not match "%s" to a log level.', $value));
            });
    }

    abstract protected function doCreate(array $options): HandlerInterface;

    private function getOptionsResolver(): OptionsResolver
    {
        return $this->optionsResolver ?? $this->optionsResolver = $this->createOptionsResolver();
    }
}
