<?php

/**
 * Copyright © Resurs Bank AB. All rights reserved.
 * See LICENSE for license details.
 */

declare(strict_types=1);

namespace Resursbank\MerchantApi\Logger;

use Exception;
use Monolog\Handler\StreamHandler;
use Monolog\Logger as Monolog;
use Resursbank\MerchantApi\Config\Config;
use Resursbank\MerchantApi\Exception\UndefinedValueException;

use function defined;

/**
 * Implement methods to write log messages.
 *
 * @todo Could potentially be replaced by PSR since it's present in both Magento and Prestashop.
 */
class Logger implements LoggerInterface
{
    /**
     * @var Monolog
     */
    private Monolog $logger;

    /**
     * Name of the channel for the Monolog (overwritten by child class).
     *
     * @var string
     */
    protected string $loggerName = '';

    /**
     * Filename where entries are stored (overwritten by child class).
     *
     * @var string
     */
    protected string $file = '';

    /**
     * @var Config
     */
    private Config $config;

    /**
     * @param Config $config
     * @param Monolog $logger
     * @param string $file
     *
     * @throws UndefinedValueException
     * @throws Exception
     */
    public function __construct(
        Config $config,
        Monolog $logger,
        string $file
    ) {
        if (!defined('_PS_ROOT_DIR_')) {
            throw new UndefinedValueException(
                'Missing constant _PS_ROOT_DIR_'
            );
        }

        $logger->pushHandler(new StreamHandler(
            _PS_ROOT_DIR_ . "/var/logs/$file.log",
            Monolog::INFO,
            false
        ));

        $this->logger = $logger;
        $this->config = $config;
    }

    /**
     * @param string $text
     * @param bool $force
     *
     * @return LoggerInterface
     */
    public function info(
        string $text,
        bool $force = false
    ): LoggerInterface {
        if ($force || $this->isEnabled()) {
            $this->logger->info($text);
        }

        return $this;
    }

    /**
     * @param string $text
     * @param bool $force
     *
     * @return LoggerInterface
     */
    public function error(
        string $text,
        bool $force = false
    ): LoggerInterface {
        if ($force || $this->isEnabled()) {
            $this->logger->error($text);
        }

        return $this;
    }

    /**
     * @param Exception $error
     * @param bool $force
     *
     * @return LoggerInterface
     */
    public function exception(
        Exception $error,
        bool $force = false
    ): LoggerInterface {
        /*
         * NOTE: The order of these checks are important, changing them may
         * introduce a circular dependency error (since Log classes need to log
         * Exceptions sometimes).
         */
        if ($force || $this->isEnabled()) {
            $this->logger->error(
                $error->getFile() . ' :: ' . $error->getLine() . '   -   '
                . $error->getMessage() . '   |   ' . $error->getTraceAsString()
            );
        }

        return $this;
    }

    /**
     * @return bool
     */
    public function isEnabled(): bool
    {
        return $this->config->isDebugEnabled();
    }
}
