<?php

declare(strict_types=1);

namespace mirzaev\huesos\controllers;

// Files of the project
use mirzaev\huesos\views\templater,
	mirzaev\huesos\models\core as models,
	mirzaev\huesos\models\account,
	mirzaev\huesos\models\session,
	mirzaev\huesos\models\settings,
	mirzaev\huesos\models\cart,
	mirzaev\huesos\models\suspension,
	mirzaev\huesos\models\enumerations\language,
	mirzaev\huesos\models\enumerations\currency;

// Framework for PHP
use mirzaev\minimal\core as minimal,
	mirzaev\minimal\controller,
	mirzaev\minimal\http\response,
	mirzaev\minimal\http\enumerations\status;

/**
 * Core of controllers
 *
 * @package mirzaev\huesos\controllers
 *
 * @param settings $settings Instance of the settings
 * @param session $session Instance of the session
 * @param account|null $account Instance of the account
 * @param cart|null $cart Instance of the cart
 * @param language $language Language
 * @param currency $currency Currency
 * @param response $response Response
 * @param array $errors Registry of errors
 *
 * @method void __construct(minimal $core, bool $initialize) Constructor
 *
 * @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
 * @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
 */
class core extends controller
{
	/**
	 * Settings
	 *
	 * @var settings $settings Instance of the settings
	 */
	protected readonly settings $settings;

	/**
	 * Session
	 * 
	 * @var session|null $session Instance of the session
	 */
	protected readonly session $session;

	/**
	 * Account
	 *
	 * @var account|null $account Instance of the account
	 */
	protected readonly ?account $account;

	/**
	 * Cart
	 *
	 * @var cart|null $cart Instance of the cart
	 */
	protected readonly ?cart $cart;

	/**
	 * Language
	 *
	 * @var language $language Language
	 */
	protected language $language = language::en;

	/**
	 * Currency
	 *
	 * @var currency $currency Currency
	 */
	protected currency $currency = currency::usd;

	/**
	 * Response
	 *
	 * @see https://wiki.php.net/rfc/property-hooks (find a table about backed and virtual hooks)
	 *
	 * @var response $response Response
	 */
	protected response $response {
		// Read
		get => $this->response ??= $this->request->response();
	}

	/**
	 * Errors
	 *
	 * @var array $errors Registry of errors
	 */
	protected array $errors = [
		'session' => [],
		'account' => []
	];

	/**
	 * Constructor
	 *
	 * @param minimal $core Initialize a controller?
	 * @param bool $initialize Initialize a controller?
	 *
	 * @return void
	 *
	 * @todo 
	 * 1. settings account и session не имеют проверок на возврат null
	 * 2. TRANSIT EVERYTHING TO MIDDLEWARES
	 */
	public function __construct(minimal $core, bool $initialize = true)
	{
		// Blocking requests from CloudFlare (better to write this blocking into nginx config file)
		if (isset($_SERVER['HTTP_USER_AGENT']) && $_SERVER['HTTP_USER_AGENT'] === 'nginx-ssl early hints') return status::bruh->label;

		// For the extends system
		parent::__construct(core: $core);

		if ($initialize) {
			// Initializing is requested

			// Initializing of models core (connect to ArangoDB...)
			new models(true);

			// Initializing of the date until which the session will be active
			$expires = strtotime('+1 week');

			// Initializing of default value of hash of the session
			$_COOKIE["session"] ??= null;

			// Initializing of a session
			$this->session = new session($_COOKIE["session"], $expires, $this->errors['session']);

			// Handle a problems with initializing a session
			if (!empty($this->errors['session'])) exit(1);
			else if ($_COOKIE["session"] !== $this->session->hash) {
				// Hash of the session is changed (implies that the session has expired and recreated)

				// Write a new hash of the session to cookies
				setcookie(
					'session',
					$this->session->hash,
					[
						'expires' => $expires,
						'path' => '/',
						'secure' => true,
						'httponly' => true,
						'samesite' => 'strict'
					]
				);
			}

			// Initializing registry of account errors
			$this->errors['account'];

			// Initializing of the account 
			$this->account = $this->session->account($this->errors['account']);

			// Initializing of the settings
			$this->settings = settings::active();

			// Initializing of the language
			$this->language =  $this->account?->language ?? $this->session?->buffer['language'] ?? $this->settings?->language ?? language::en;

			// Initializing of the currency
			$this->currency = $this->account?->currency ?? $this->session?->buffer['currency'] ?? $this->settings?->currency ?? currency::usd;

			// Initializing of preprocessor of views
			$this->view = new templater(
				session: $this->session,
				account: $this->account,
				settings: $this->settings
			);

			// @todo перенести в middleware

			// Search for suspensions                                                      
			$suspension = suspension::search();

			if ($suspension && $suspension->targets['web app']) {
				// Found a suspension                                              

				if ($this->account) {
					// Initialized account

					foreach ($suspension->access as $type => $status) {
						// Перебор статусов доступа                                                   

						if ($status && $this->account->{$type}) {
							// Authorized account                                                       

							// Exit (success)                                                           
							return $this;
						}
					}

					// Exit (success)
					goto suspension;
				} else {
					// Not initialized account     

					// Send the suspension page and exit (success)
					suspension:

					// Write title of the page to templater global variables
					$this->view->title = match ($this->language) {
						language::en => 'Suspended',
						language::ru => 'Приостановлено',
						default => 'Suspended'
					};

					// Write description of the suspension to templater global variables
					$this->view->description = $suspension->description[$this->language] ?? array_values($suspension->description)[0];

					// Write message of remaining time of the suspension to templater global variables
					$this->view->remain = [
						'title' => match ($this->language) {
							language::en => 'Time remaining: ',
							language::ru => 'Осталось времени: ',
							default => 'Time remaining: '
						},
						'value' => $suspension?->message()
					];

					// Send the suspension page                                                                                    
					echo $this->view->render('suspension/page.html');

					// Exit (success)                                                                                              
					exit(0);
				}
			}
		}
	}
}
