<?php

declare(strict_types=1);

namespace kodorvan\surikov\controllers;

// The project
use kodorvan\surikov\controllers\core,
kodorvan\surikov\models\account;

// Framework for PHP
use mirzaev\minimal\http\enumerations\content,
mirzaev\minimal\http\enumerations\protocol,
mirzaev\minimal\http\enumerations\status;

/**
 * Accounts controller
 *
 * @package kodorvan\surikov\controllers
 *
 * @param array $errors Registry of errors
 *
 * @method null index() Account page
 * @method string|null registration() Registration
 *
 * @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
 * @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
 */
final class accounts extends core
{
	/**
	 * Errors
	 *
	 * @var array $errors Registry of errors
	 */
	protected array $errors = [
		'system' => [],
		'account' => []
	];

	/**
	 * Account page
	 *
	 * @return null
	 */
	public function index(): null
	{
		if (str_contains($this->request->headers['accept'] ?? '', content::any->value)) {
			// Request for any response

			// Render page
			$page = $this->view->render('pages/account/index.html');

			// Sending response
			$this->response
				->status(status::ok)
				->start()
				->clean()
				->sse()
				->write($page)
				->validate($this->request)
					?->body()
				->end();

			// Deinitializing rendered page
			unset($page);

			// Exit (success)
			return null;
		}

		// Exit (fail)
		return null;
	}

	/**
	 * Registration
	 *
	 * @param string|null $mail Mail
	 * @param string|null $password Password
	 * @param int|string|bool|null $remember Remember
	 * @param string|null $redirect Redirect @deprecated
	 *
	 * @return null
	 */
	public function registration(
		?string $mail = null,
		?string $password = null,
		int|string|bool|null $remember = null,
		?string $redirect = null
	): null {
		if ($this->view->account = account::registrate(mail: $mail, password: $password, errors: $this->errors['account'])) {
			// Registered

			// Filtering the remember argument
			$remember = (bool) $remember;

			if ($this->view->account = account::authenticate(mail: $mail, password: $password, remember: $remember, errors: $this->errors['account'])) {
				// Authenticated
			} else {
				// Not authenticated

				// Sending response
				$this->response
					->status(status::forbidden)
					->start()
					->clean()
					->sse()
					->validate($this->request)
						?->body()
					->end();
			}
		} else {
			// Not registered
			var_dump($this->errors);
			die;
			// Sending response
			$this->response
				->status(status::unauthorized)
				->start()
				->clean()
				->sse()
				->validate($this->request)
					?->body()
				->end();
		}

		// Initializing path to redirecting @deprecated
		$redirect ??= $_SERVER['HTTP_REFERER'] ?? '/';

		// Redirecting
		header("Location: $redirect", response_code: status::see_other->value);

		// Exit (success)
		return null;
	}

	/**
	 * Authentication
	 *
	 * @param string|null $mail Mail
	 * @param string|null $password Password
	 * @param int|string|bool|null $remember Remember
	 * @param string|null $redirect Redirect @deprecated
	 *
	 * @return null
	 */
	public function authentication(
		?string $mail = null,
		?string $password = null,
		int|string|bool|null $remember = null,
		?string $redirect = null
	): ?string {
		// Filtering the remember argument
		$remember = (bool) $remember;

		if ($this->view->account = account::authenticate(mail: $mail, password: $password, remember: $remember, errors: $this->errors['account'])) {
			// Authenticated
		} else {
			// Not authenticated

			// Sending response
			$this->response
				->status(status::forbidden)
				->start()
				->clean()
				->sse()
				->validate($this->request)
					?->body()
				->end();
		}

		// Initializing path to redirecting @deprecated
		$redirect ??= $_SERVER['HTTP_REFERER'] ?? '/';

		// Redirecting
		header("Location: $redirect", response_code: status::see_other->value);

		// Exit (success)
		return null;
	}

	/**
	 * Deauthentication
	 *
	 * @return null
	 */
	public function deauthentication(): null
	{
		if (account::deauthenticate(errors: $this->errors['account'])) {
			// Deauthenticated
		} else {
			// Not deauthenticated

			// Sending response
			$this->response
				->status(status::internal_server_error)
				->start()
				->clean()
				->sse()
				->validate($this->request)
					?->body()
				->end();
		}

		// Перенаправление
		header('Location: /', response_code: status::see_other->value);

		// Exit (success)
		return null;
	}

	/**
	 * Data
	 *
	 * If the information requested is not by an administrator, 
	 * only publicly permitted information will be returned.
	 *
	 * @param int|null $identifier Identifier
	 *
	 * @return string JSON-документ
	 */
	public function data(?int $identifier = null): ?string
	{
		if ($account = account::read(expressions: ['identifier' => $identifier], errors: $this->errors['account'])) {
			// Found the account

			// Initializing the account
			$this->view->account = account::initialize(errors: $this->errors['account']);

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

				if ($this->view->account->permissions['accounts'] ?? 0 === 1) {
					// Authorized to accounts
				} else {
					// Not authorized to accounts

					// Deinitializing the account private properties
					unset($account->password, $account->hash, $account->time);
				}

				if (str_contains($this->request->headers['accept'] ?? '', content::any->value)) {
					// Request for any response

					// Render page
					$page = $this->view->render('pages/account/index.html');

					// Sending response
					$this->response
						->status(status::ok)
						->start()
						->clean()
						->sse()
						->json($account)
						->validate($this->request)
							?->body()
						->end();

					// Deinitializing rendered page
					unset($page);

					// Exit (success)
					return null;
				}
			}
		} else {
			// Not found the account

			// Sending response
			$this->response
				->status(status::not_found)
				->start()
				->clean()
				->sse()
				->validate($this->request)
					?->body()
				->end();
		}

		// Exit (success)
		return null;
	}
}
