<?php

namespace Mnv\Core\Test;


use Mnv\Core\Config;

/**
 * Class Testing
 * @package Mnv\Models
 */
class Testing
{

    private bool $show_debug    = false;
    private static $existErrors;
    private static $fileLog;

    public string $alert = '';

    /**
     * Testing constructor.
     */
    public function __construct()
    {
        $this->show_debug = Config::getValue('error_test');

        $gmDate = adjustTime(gmdate('Y-m-d H:i:s'), false, 'Y-m-d');

        self::$fileLog = ERRORS_LOG . 'app-'.$gmDate.'.log';

        set_error_handler(array($this, 'debug_critical_error'));

		# default : error hide
		self::error_report($this->show_debug);
        # check error log
        self::check_error_log();

    }


    private static function check_error_log(): void
    {
		if (is_file(self::$fileLog) && filesize(self::$fileLog) != 0) {
			self::$existErrors = true;
		}

		if (is_file(ERRORS_LOG . 'syserrors.log') && filesize(ERRORS_LOG . 'syserrors.log') != 0) {
            self::$existErrors = true;
		}
	}



	/**
	 * System Error Interceptor
	 *
	 * @param mixed $errno - error number
	 * @param mixed $msg   - message od error
	 * @param mixed $file  - filename with error
	 * @param mixed $line  - string number with error
	 */
	public function debug_critical_error($errno, $msg, $file, $line)
    {

        $subj = file_read(self::$fileLog);

        switch($errno) {
	        case E_ERROR:			# critical
		        $erlevel = 0;
                $ercode  = "E_ERROR";
		        break;

	        case E_USER_ERROR:		# critical
		        $erlevel = 0;
                $ercode  = "E_USER_ERROR";
		        break;

	        case E_RECOVERABLE_ERROR :	# warning(?)critical
		        $erlevel = 1;
                $ercode  = "E_RECOVERABLE_ERROR";
		        break;

	        case E_WARNING:			# warning
		        $erlevel = 1;
                $ercode  = "E_WARNING";
		        break;

	        case E_USER_WARNING:		# warning
		        $erlevel = 1;
                $ercode  = "E_USER_WARNING";
		        break;

	        case E_CORE_WARNING:		# warning
		        $erlevel = 1;
                $ercode  = "E_CORE_WARNING";
		        break;

	        case E_COMPILE_WARNING:		# warning
		        $erlevel = 1;
                $ercode  = "E_COMPILE_WARNING";
		        break;

	        case E_NOTICE:			# notice
		        $erlevel = 2;
		        $ercode  = "E_NOTICE";
		        break;

	        case E_USER_NOTICE:		# notice
		        $erlevel = 2;
                $ercode  = "E_USER_NOTICE";
		        break;

	        default:			# unknown
		        $erlevel = 3;
                $ercode  = "";
		        break;
        }

        $time = date("d.m.Y H:i");

        $subj .= $time . " | " . getenv('REMOTE_ADDR') . " | " . $_SERVER['REQUEST_URI'] . " | " . $ercode . " | " . $errno . " | " . $msg . " | " . $line . " | " . $file . "\r\n";

        $f = fopen(self::$fileLog, "w+");
        if (is_writable(self::$fileLog)) {
            fwrite($f, $subj);
        }
        fclose($f);

		# hide error if not use debug mode
		if (error_reporting() == 0 && $erlevel == 0) {
            return ("<blockquote style='padding: 1rem; margin: .2rem .4rem;border: 1px solid moccasin;background-color: lemonchiffon;color: #1e1e1e;font-size: .85rem;'>
					Извините, что то пошло не так. Мы уже работаем над устранением причин. <small>".$time."</small> 
				    <a href='javascript:history.back(1)'>< Вернуться назад</a></blockquote>");
		}

        if ($this->show_debug) {
            print "<div class='alert alert-danger alert-dismissible fade show'>" .
			"Error: <span class='fw-semibold'> #{$errno} - {$ercode}</span><br />" .
			"Строка: <span class='fw-semibold'>{$line}</span> в файле <span class='fw-semibold'>{$file}</span><br />" .
			"<span class='fw-semibold'>{$msg}</span></div>\n";

		} else {
           $this->alert = "<div class='alert alert-danger alert-dismissible fade show'>
            Error: <span class='fw-semibold'> #{$errno} - {$ercode}</span><br />
            Строка: <span class='fw-semibold'>{$line}</span> в файле <span class='fw-semibold'>{$file}</span><br />
            <span class='fw-semibold'>{$msg}</span></div>\n";
        }

		# Мы убиваем стандартного обработчика, чтобы он ничего не выдал шпиону (:
		return true;
	}

	private static function error_report($show = false): void
    {
		ini_set("error_log", ERRORS_LOG . 'syserrors.log');
		if ($show) {
			error_reporting(E_ALL);			     #8191
			ini_set("display_startup_errors",	1);
			ini_set("display_errors",		    1);
			ini_set("html_errors",			    1);
			ini_set("report_memleaks",		    1);
			ini_set("log_errors",			    1);
			ini_set("log_errors_max_len",		2048);
			ini_set("ignore_repeated_errors",	1);
			ini_set("ignore_repeated_source",	1);
		} else {
			error_reporting(0);
		}
	}



    public static function productivityTime($startTime): float
    {
        $endTime = microtime(true);
        return round(($endTime - $startTime), 4);
    }

    public static function memoryPeakUsage(): float
    {
        return round((memory_get_peak_usage()/1024)/1024, 2);
    }

    public static function productivityMemory(): float
    {
        return round((memory_get_usage() / 1024)/1024, 2);
    }
}