<?php

declare(strict_types=1);

namespace VK\Loggers;

use \DateTime;
use \Monolog\Logger;
use \Monolog\Handler\StreamHandler;
use \Jasny\ErrorHandler;
use \VK\Core;
use \VK\Traits\Singleton;

/**
 * Журналист Jasmo
 * 
 * Основан на "monolog/monolog" и "jasny/error-handler" 
 * Monolog + Jasny = Jasmo
 * 
 * @package Log
 * @author Arsen Mirzaev
 */
class Jasmo extends LoggerAbstract
{
    use Singleton;
    
    /**
     * Экземпляр класса журналиста
     *
     * @var Logger
     */
    public static $logger;

    // /**
    //  * Экземпляр класса обработчика ошибок
    //  *
    //  * @var ErrorHandler 
    //  */
    // public ErrorHandler $handler;

    public static function post($file = null): ?Jasmo
    {
        $file = $file ?? date_format(new DateTime(Core::$timezone), 'Y.m.d');

        /** 
         * Создание логгера по спецификации PSR-3 (Monolog)
         * 
         * @param string Название канала логирования
         */
        self::$logger = new Logger(__CLASS__);

        /** 
         * Создание обработчиков (порядок обязателен) 
         */
        self::$logger->pushHandler(new StreamHandler(Core::$path['log'] . "/${file}-INFO.log", Logger::INFO, false));               // Инфомация о процессе работы
        self::$logger->pushHandler(new StreamHandler(Core::$path['log'] . "/${file}-NOTICE.log", Logger::NOTICE, false));           // Уведомления
        self::$logger->pushHandler(new StreamHandler(Core::$path['log'] . "/${file}-WARNING.log", Logger::WARNING, false));         // Предупреждения
        self::$logger->pushHandler(new StreamHandler(Core::$path['log'] . "/${file}-ERROR.log", Logger::ERROR, false));             // Ошибки
        self::$logger->pushHandler(new StreamHandler(Core::$path['log'] . "/${file}-CRITICAL.log", Logger::CRITICAL, false));       // Критические ошибки
        self::$logger->pushHandler(new StreamHandler(Core::$path['log'] . "/${file}-ALERT.log", Logger::ALERT, false));             // Критические ошибки
        self::$logger->pushHandler(new StreamHandler(Core::$path['log'] . "/${file}-EMERGENCY.log", Logger::EMERGENCY, false));     // Критические ошибки
        self::$logger->pushHandler(new StreamHandler(Core::$path['log'] . "/$file.log", Logger::DEBUG));                            // Общий лог

        // test
        // self::$logger->pushProcessor(function ($record) {
        //     $record['extra']['dummy'] = 'Hello world!';

        //     return $record;
        // });
        
        echo '[' . date_format(new DateTime(Core::$timezone), 'd-m-Y H:i:s') . '] Начало работы', PHP_EOL;
        self::$logger->info('Начало работы');

        return self::$instance;
    }

    public static function get(): ?Jasmo
    {
        return self::$instance;
    }

    public static function delete(): ?Jasmo
    {
        return self::$instance;
    }

    public static function postErrorHandler(): ?Jasmo
    {
        /** 
         * Подключение логгера в обработчик ошибок (Jasny)
         */
        $handler = new ErrorHandler(self::$logger);

        $handler->logUncaught(E_ALL); // Обрабатывать все ошибки
        $handler->onFatalError(function ($error) {
            self::$logger->error($error);
        }, true);

        return self::$instance;
    }

    public static function deleteErrorHandler(): ?Jasmo
    {
        return self::$instance;
    }

    public static function postShutdownHandler(): ?Jasmo
    {
        register_shutdown_function(array(self::$instance, 'handlerShutdown'));

        return self::$instance;
    }

    
    public function handlerShutdown(): void
    {
        self::$logger->info('Завершение работы');
        echo '[' . date_format(new DateTime(Core::$timezone), 'd-m-Y H:i:s') . '] Завершение работы', PHP_EOL;
    }

    // public function handlerErrors($errno, $errstr, $errfile, $errline, $errcontext): bool
    // {
    //     echo "друг, да ты вероянто напортачил $errno $errstr", PHP_EOL, PHP_EOL;
    //     if ($this->logger->error("друг, да ты вероянто напортачил $errno $errstr")) {
    //         return true;
    //     } else {
    //         return false;
    //     }
    // }
}