<?php

declare(strict_types=1);

namespace mirzaev\ebala\controllers;

// Файлы проекта
use mirzaev\ebala\views\templater,
	mirzaev\ebala\models\core as model,
	mirzaev\ebala\models\account,
	mirzaev\ebala\models\session,
	mirzaev\ebala\models\market;

// Фреймворк PHP
use mirzaev\minimal\controller;

// Встроенные библиотеки
use exception;

/**
 * Ядро контроллеров
 *
 * @package mirzaev\ebala\controllers
 * @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
 */
class core extends controller
{
	/**
	 * Постфикс
	 */
	final public const POSTFIX = '';

	/**
	 * Инстанция сессии
	 */
	protected readonly session $session;

	/**
	 * Инстанция аккаунта
	 */
	protected readonly ?account $account;

	/**
	 * Реестр ошибок
	 */
	protected array $errors = [
		'session' => [],
		'account' => []
	];

	/**
	 * Конструктор
	 *
	 * @param bool $initialize Инициализировать контроллер?
	 */
	public function __construct(bool $initialize = true)
	{
		// Блокировка запросов от CloudFlare
		if ($_SERVER['HTTP_USER_AGENT'] === 'nginx-ssl early hints') return;

		parent::__construct($initialize);

		if ($initialize) {
			// Запрошена инициализация

			// Инициализация ядра моделей (соединение с базой данных...)
			new model();

			// Инициализация даты до которой будет активна сессия
			$expires = strtotime('+1 week');

			// Инициализация значения по умолчанию
			$_COOKIE["session"] ??= null;

			// Инициализация сессии
			$this->session = new session($_COOKIE["session"], $expires, $this->errors['session']);
			if (!empty($this->errors['session'])) die;
			else if ($_COOKIE["session"] !== $this->session->hash) {
				// Изменился хеш сессии (подразумевается, что сессия устарела)

				// Запись хеша новой сессии
				setcookie(
					'session',
					$this->session->hash,
					[
						'expires' => $expires,
						'path' => '/',
						'secure' => true,
						'httponly' => true,
						'samesite' => 'strict'
					]
				);
			}

			// Инициализация аккаунта
			$this->account = new account($this->session);

			if ($this->account->status()) {
				// Инициализирован аккаунт

				if ($this->account->type !== $_SERVER['INTERFACE']) {
					// Не соответствие типа аккаунта к запрошенному интерфейсу (например, если оператор зашел на интерфейс магазина)

					// Переадресация
					header(
						'Location: '
							. $_SERVER['SCHEME']
							. '://'
							. match ($this->account->type) {
								'worker' => 'панель',
								'operator' => 'оператор',
								'market' => 'магазин',
								'administrator' => 'администратор',
								default => 'панель'
							}
							. '.'
							. $_SERVER['DOMAIN']
							. $_SERVER['REQUEST_URI'],
						true,
						303
					);

					// Выход (успех)
					return;
				}
			}

			// Инициализация шаблонизатора представлений
			$this->view = new templater($this->session, $this->account);
		}
	}

	protected function authorization(): string
	{
		if ($_SERVER['INTERFACE'] === 'operator') {
			// Оператор

			// Инициализация данных аккаунтов для генерации представления
			$this->view->accounts = account::read('d.type == "operator" && d.active == true', 'd.name.first DESC, d._key DESC', 100, 1, errors: $this->errors['account']);

			// Преобразование в массив, если вернуло инстанцию одного документа, вместо массива инстанций документов
			if (!is_array($this->view->accounts)) $this->view->accounts = [$this->view->accounts];
		} else if ($_SERVER['INTERFACE'] === 'market') {
			// Магазин

			// Инициализация данных аккаунтов для генерации представления
			$this->view->accounts = account::read('d.type == "market" && d.active == true', 'd.name.first DESC, d._key DESC', 100, 1, errors: $this->errors['account']);

			// Преобразование в массив, если вернуло инстанцию одного документа, вместо массива инстанций документов
			if (!is_array($this->view->accounts)) $this->view->accounts = [$this->view->accounts];

			// Инициализация буфера оболочки аккаунта и магазина
			$buffer = [];

			// Инициализация данных магазина для аккаунта для генерации представления
			foreach ($this->view->accounts as $account) $buffer[] = ['account' => $account, 'market' => account::market($account->getId(), errors: $this->errors['account'])];

			// Запись в глобальную переменную из буфера
			$this->view->accounts = $buffer;
		} else if ($_SERVER['INTERFACE'] === 'administrator') {
			// Администратор

			// Инициализация данных аккаунтов для генерации представления
			$this->view->accounts = account::read('d.type == "administrator" && d.active == true', 'd.name.first DESC, d._key DESC', 100, 1, errors: $this->errors['account']);

			// Преобразование в массив, если вернуло инстанцию одного документа, вместо массива инстанций документов
			if (!is_array($this->view->accounts)) $this->view->accounts = [$this->view->accounts];
		}

		return $this->view->render(DIRECTORY_SEPARATOR . 'pages' . DIRECTORY_SEPARATOR . 'entry' . DIRECTORY_SEPARATOR . $_SERVER['INTERFACE'] . '.html');
	}

	/**
	 * Проверить инициализированность
	 *
	 * Проверяет инициализированность свойства в инстанции документа аккаунта из базы данных
	 *
	 * @param string $name Название
	 *
	 * @return bool Свойство инициализировано?
	 */
	public function __isset(string $name): bool
	{
		return match ($name) {
			'account' => isset($this->account->document),
			default => isset($this->{$name})
		};
	}
}
