<?php

declare(strict_types=1);

namespace mirzaev\huesos\models;

// Files of the project
use mirzaev\huesos\models\core,
	mirzaev\huesos\controllers\core as controller,
	mirzaev\huesos\models\catalog,
	mirzaev\huesos\models\suspension,
	mirzaev\huesos\models\account,
	mirzaev\huesos\models\enumerations\language,
	mirzaev\huesos\models\enumerations\currency;

// Framework for Telegram
use Zanzara\Zanzara,
	Zanzara\Context as context,
	Zanzara\Telegram\Type\Input\InputFile,
	Zanzara\Telegram\Type\File\Document as telegram_document,
	Zanzara\Middleware\MiddlewareNode as Node,
	Zanzara\Telegram\Type\User as user;

// Framework for ArangoDB
use mirzaev\arangodb\document;

/**
 * Model of chat (telegram)
 *
 * @package mirzaev\huesos\models
 *
 * @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
 * @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
 */
final class telegram extends core
{
	/**
	 * Экранирование символов для Markdown
	 *
	 * @param string $text Текст для экранирования
	 * @param array $exception Символы которые будут исключены из списка для экранирования
	 *
	 * @return string Экранированный текст
	 */
	public static function unmarkdown(string $text, array $exceptions = []): string
	{
		// Инициализация реестра символом для конвертации
		$from = array_diff(
			[
				'#',
				'*',
				'_',
				'=',
				'.',
				'[',
				']',
				'(',
				')',
				'-',
				'>',
				'<',
				'!',
				'`'
			],
			$exceptions
		);

		// Инициализация реестра целей для конвертации
		$to = [];
		foreach ($from as $symbol) $to[] = "\\$symbol";

		// Конвертация и выход (успех)
		return str_replace($from, $to,	$text);
	}

	/**
	 * Инициализация запчасти
	 *
	 * Проверяет существование запчасти
	 *
	 * @param string $spare Запчасть
	 *
	 * @return string|bool Запчасть, если найдена, иначе false
	 */
	public static function spares(string $spare): string|bool
	{
		// Поиск запчастей и выход (успех)
		return match (mb_strtolower($spare)) {
			'цевьё' => 'Цевьё',
			default => false
		};
	}

	/**
	 * Главное меню
	 *
	 * Команда: /start
	 *
	 * @param context $ctx
	 *
	 * @return void
	 */
	public static function menu(context $ctx): void
	{
		// Declaring keyboard buttond
		$keyboard = [];

		/* if ($ctx->get('account')) {
			// Authenticated */

		// Writing the catalog button
		$keyboard[] = [
			[
				'text' => '🛒 Каталог',
				'web_app' => ['url' => 'https://telegram.arming.ru/']
			]
		];
		/* } */

		$keyboard = array_merge(
			$keyboard,
			[[
				['text' => '🏛️ О компании'],
				['text' => '💬 Контакты']
			]],
			[[
				['text' => '🎯 Сообщество']
			]]
		);


		if ($ctx->get('account')?->access['settings']) $keyboard[] = [['text' => '⚙️  Настройки']];

		// Отправка сообщения
		$ctx->sendMessage(
			static::unmarkdown(<<<TXT
		Это сообщение будет отображаться (оно должно быть обязательно) при вызове главного меню командой /start (создаёт кнопки меню снизу)
		TXT),
			[
				'reply_markup' => [
					'keyboard' => $keyboard,
					'resize_keyboard' => true
				],
				'disable_notification' => true
			]
		);
	}

	/**
	 * Начало работы с чат-роботом
	 *
	 * Команда: /start
	 *
	 * @param context $ctx
	 *
	 * @return void
	 */
	public static function start(context $ctx): void
	{
		// Главное меню
		static::menu($ctx);
	}

	/**
	 * Контакты
	 *
	 * Команда: /contacts
	 *
	 * @param context $ctx
	 *
	 * @return void
	 */
	public static function contacts(context $ctx): void
	{
		// Отправка сообщения
		$ctx->sendMessage(static::unmarkdown(<<<TXT
		Здесь придумать текст для раздела "Контакты"
		TXT), [
			'reply_markup' => [
				'inline_keyboard' => [
					[
						['text' => '⚡ Связь с менеджером', 'url' => 'https://t.me/iarming'],
					],
					[
						['text' => '📨 Почта', 'callback_data' => 'mail']
					],
					[
						['text' => '🪖 Сайт', 'url' => 'https://arming.ru'],
						['text' => '🛒 Wildberries', 'url' => 'https://www.wildberries.ru/seller/137386'],
						['text' => '🛒 Ozon', 'url' => 'https://www.ozon.ru/seller/arming-1086587/products/?miniapp=seller_1086587'],
					]
				]
			],
			'link_preview_options' => [
				'is_disabled' => true
			],
			'disable_notification' => true
		]);
	}

	/**
	 * Почта
	 *
	 * @param context $ctx
	 *
	 * @return void
	 */
	public static function _mail(context $ctx): void
	{
		// Отправка сообщения
		$ctx->sendMessage(static::unmarkdown(<<<TXT
		[info@arming.ru](mailto::info@arming.ru)
		TXT, ['[', ']', '(', ')']), [
			'link_preview_options' => [
				'is_disabled' => true
			],
			'disable_notification' => true
		]);
	}

	/**
	 * Компания
	 *
	 * Команда: /company
	 *
	 * @param context $ctx
	 *
	 * @return void
	 */
	public static function company(context $ctx): void
	{
		// Отправка сообщения
		$ctx->sendMessage(
			static::unmarkdown(<<<TXT
			Здесь придумать текст для раздела "Компания"
			TXT),
			[
				'reply_markup' => [
					'inline_keyboard' => [
						[
							['text' => '📄 Публичная оферта', 'web_app' => ['url' => 'https://telegram.arming.ru/offer']],
						]
					]
				],
				'link_preview_options' => [
					'is_disabled' => true
				]
			]
		);
	}

	/**
	 * Сообщество
	 *
	 * Команда: /community
	 *
	 * @param context $ctx
	 *
	 * @return void
	 */
	public static function community(context $ctx): void
	{
		// Отправка сообщения
		$ctx->sendMessage(static::unmarkdown(<<<TXT
		Здесь придумать текст для раздела "Сообщество"
		TXT), [
			'reply_markup' => [
				'inline_keyboard' => [
					[
						['text' => '💬 Основной чат', 'url' => 'https://t.me/arming_zone'],
					]
				]
			],
			'link_preview_options' => [
				'is_disabled' => true
			],
			'disable_notification' => true
		]);
	}

	/**
	 * Настройки (доступ только авторизованным)
	 *
	 * Команда: /settings
	 *
	 * @param context $ctx
	 *
	 * @return void
	 */
	public static function settings(context $ctx): void
	{
		if ($ctx->get('account')?->access['settings']) {
			// Авторизован доступ к настройкам

			// Отправка сообщения
			$ctx->sendMessage(
				static::unmarkdown(<<<TXT
				Панель управления чат-роботом ARMING
				TXT),
				[
					'reply_markup' => [
						'inline_keyboard' => [
							[
								['text' => '📦 Импорт товаров', 'callback_data' => 'import_request'],
							]
						]
					],
					'link_preview_options' => [
						'is_disabled' => true
					],
					'disable_notification' => true
				]
			);
		} else {
			// Не авторизован доступ к настройкам

			// Отправка сообщения
			$ctx->sendMessage('⛔ *Нет доступа*');
		}
	}

	/**
	 * Запросить файл для импорта товаров (доступ только авторизованным)
	 *
	 * @param context $ctx
	 *
	 * @return void
	 */
	public static function import_request(context $ctx): void
	{
		if ($ctx->get('account')?->access['settings']) {
			// Авторизован доступ к настройкам

			// Отправка сообщения
			$ctx->sendMessage(static::unmarkdown('Отправьте документ в формате xlsx со списком товаров'))
				->then(function ($message) use ($ctx) {
					// Отправка файла
					$ctx->sendDocument(new InputFile(CATALOG_EXAMPLE), ['disable_notification' => true]);

					// Импорт файла
					$ctx->nextStep([static::class, 'import'], true);
				});
		} else {
			// Не авторизован доступ к настройкам

			// Отправка сообщения
			$ctx->sendMessage('⛔ *Нет доступа*');
		}
	}

	/**
	 * Импорт товаров (доступ только авторизованным)
	 *
	 * @param context $ctx
	 *
	 * @return void
	 */
	public static function import(context $ctx): void
	{
		if (($account = $ctx->get('account'))?->access['settings']) {
			// Авторизован доступ к настройкам

			// Инициализация документа
			$document = $ctx->getMessage()?->getDocument();

			if ($document instanceof telegram_document) {
				// Инициализирован документ

				// Инициализация файла
				$ctx->getFile($document->getFileId())->then(function ($file) use ($ctx, $document, $account) {

					if ($file->getFileSize() <= 50000000) {
						// Не превышает 50 мегабайт (50 000 000 байт) размер файла

						if (pathinfo(parse_url($file->getFilePath())['path'], PATHINFO_EXTENSION) === 'xlsx') {
							// Имеет расширение xlsx файл

							// Initializing the directory in the storage
							if (!file_exists($storage = STORAGE . DIRECTORY_SEPARATOR . 'import' . DIRECTORY_SEPARATOR . $account->getKey() . DIRECTORY_SEPARATOR . time()))
								mkdir($storage, 0775, true);

							// Сохранение файла
							file_put_contents(
								$import = $storage . DIRECTORY_SEPARATOR . 'import.xlsx',
								file_get_contents('https://api.telegram.org/file/bot' . KEY . '/' . parse_url($file->getFilePath())['path'])
							);

							// Отправка сообщения
							$ctx->sendMessage(sprintf(
								<<<'TXT'
								🔬 *Выполняется анализ:* %s \(%s байт\)
								TXT,
								static::unmarkdown($document->getFileName()),
								static::unmarkdown((string) $file->getFileSize())
							))
								->then(function ($message) use ($ctx, $import) {
									// Инициализация счётчика загруженных товаров
									$categories_loaded
										= $products_loaded
										= $categories_created
										= $products_created
										= $categories_updated
										= $products_updated
										= $categories_deleted
										= $products_deleted
										= $categories_old
										= $products_old
										= $categories_new
										= $products_new
										= 0;

									// Import
									catalog::import(
										$import,
										$categories_loaded,
										$categories_created,
										$categories_updated,
										$categories_deleted,
										$categories_old,
										$categories_new,
										$products_loaded,
										$products_created,
										$products_updated,
										$products_deleted,
										$products_old,
										$products_new,
										language: $account->language ?? settings::active()?->language ?? language::en, // @todo add languages
										currency: $account->currency ?? settings::active()?->currency ?? currency::usd // @todo add currencies
									);

									// Отправка сообщения
									$ctx->sendMessage(<<<TXT
										🏷 *Категории*

										*Загружено:* $categories_loaded

										*Добавлено:* $categories_created
										*Обновлено:* $categories_updated
										*Удалено:* $categories_deleted

										*Было:* $categories_old
										*Стало:* $categories_new
										TXT)
										->then(function ($message) use ($ctx, $products_loaded, $products_created, $products_updated, $products_deleted, $products_old, $products_new) {
											$ctx->sendMessage(<<<TXT
												📦 *Товары*

												*Загружено:* $products_loaded

												*Добавлено:* $products_created
												*Обновлено:* $products_updated
												*Удалено:* $products_deleted

												*Было:* $products_old
												*Стало:* $products_new
												TXT)
												->then(function ($message) use ($ctx) {
													// Завершение диалога
													$ctx->endConversation();
												});
										});
								});
						} else {
							// Не имеет расширение xlsx файл

							// Отправка сообщения
							$ctx->sendMessage(static::unmarkdown('Файл должен иметь расширение xlsx'));
						}
					} else {
						// Превышает 50 мегабайт (50000000 байт) размер файла

						// Отправка сообщения
						$ctx->sendMessage(static::unmarkdown('Размер файла не должен превышать 50 мегабайт'));
					}
				});
			} else {
				// Не инициализирован документ

				// Отправка сообщения
				$ctx->sendMessage(static::unmarkdown('Отправьте документ в формате xlsx со списком товаров'));
			}
		} else {
			// Не авторизован доступ к настройкам

			// Отправка сообщения
			$ctx->sendMessage('⛔ *Нет доступа*');
		}
	}

	/**
	 * Инициализация аккаунта (middleware)
	 *
	 * @param context $ctx
	 * @param Node $next
	 *
	 * @return void
	 */
	public static function account(context $ctx, Node $next): void
	{
		// Выполнение заблокировано?
		if ($ctx->get('stop')) return;

		// Инициализация аккаунта Telegram
		$telegram = $ctx->getEffectiveUser();

		// Инициализация аккаунта
		$account = account::initialize($telegram->getId(), $telegram);

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

			if ($account->banned) {
				// Заблокирован аккаунт

				// Отправка сообщения
				$ctx->sendMessage('⛔ *Ты заблокирован*')
					->then(function ($message) use ($ctx) {
						// Завершение диалога
						$ctx->endConversation();
					});

				// Блокировка дальнейшего выполнения
				$ctx->set('stop', true);
			} else {
				// Не заблокирован аккаунт

				// Запись в буфер
				$ctx->set('account', $account);

				// Продолжение выполнения
				$next($ctx);
			}
		} else {
			// Не инициализирован аккаунт
		}
	}

	/**
	 * Инициализация статуса технических работ (middleware)
	 *
	 * @param context $ctx
	 * @param Node $next
	 *
	 * @return void
	 */
	public static function suspension(context $ctx, Node $next): void
	{
		// Выполнение заблокировано?
		if ($ctx->get('stop')) return;

		// Поиск технических работ
		$suspension = suspension::search();

		if ($suspension && $suspension->targets['telegram-robot']) {
			// Найдена активная приостановка

			// Инициализация аккаунта
			$account = $ctx->get('account');

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

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

					if ($status && $account->{$type}) {
						// Авторизован аккаунт

						// Продолжение выполнения
						$next($ctx);

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

			// Инициализация сообщения
			$message = "⚠️ *Работа приостановлена*\n*Оставшееся время\:* " . $suspension->message($account->language ?? settings::active()?->language ?? 'en');

			// Добавление описания причины приостановки, если найдена
			if (!empty($suspension->description))
				$message .= "\n\n" . $suspension->description[$account->language ?? settings::active()?->language ?? 'en'] ?? array_values($suspension->description)[0];

			// Отправка сообщения
			$ctx->sendMessage($message)
				->then(function ($message) use ($ctx) {
					// Завершение диалога
					$ctx->endConversation();
				});

			// Блокировка дальнейшего выполнения
			$ctx->set('stop', true);
		} else {
			// Не найдена активная приостановка

			// Продолжение выполнения
			$next($ctx);
		}
	}

	/**
	 * Cart attach
	 *
	 * @param context $ctx
	 * @param string $share Sharing hash
	 *
	 * @return void
	 */
	public static function cart_attach(context $ctx, string $share): void
	{
		// Initializing account
		$account = $ctx->get('account');

		if ($account) {
			// Initialized the account

			// Initializing cart
			$cart = cart::_read(
				filter: 'd.share == @share',
				sort: 'd.updated DESC, d.created DESC, d._key DESC',
				amount: 1,
				page: 1,
				parameters: ['share' => $share]
			);

			// Deinitializing unnecessary variables
			unset($share);

			// Unsharing the cart
			$cart->unshare();

			if ($cart instanceof cart) {
				// Initialized the cart

				// Connecting the cart to the account
				$edge = $account->connect($cart);

				if (!empty($edge)) {
					// Connected the cart to the account

					// Initializing products in the cart
					$products = $cart->products(language: $account->language ?? language::ru, currency: $account->currency ?? currency::rub);

					if (!empty($products)) {
						// Initialized products in the cart

						// Declaring total cost of products
						$cost = 0;

						// Declaring formatted list of products for message
						$list = '';

						// Initializing iterator of rows
						$row = 0;

						foreach ($products as $product) {
							// Iterating over products

							// Generating formatted list of products for message
							$list .= static::unmarkdown(++$row . '. ' . $product['document']['name'] . ' (' . $product['amount'] . 'шт)') . "\n";

							// Generating total cost of products
							$cost += $product['document']['cost'] * $product['amount'];
						}

						// Deinitializing unnecessary variables
						unset($products, $product, $row);

						// Initializing identifier of the cart
						$identifier = $cart->getKey();

						// Initializing currency symbol
						$symbol = ($account->currency ?? currency::rub)->symbol();

						// Initializing delivery cost for message
						$delivery_cost = $cart->buffer['delivery']['cost'];

						// Initializing delivery days for message
						$delivery_days = $cart->buffer['delivery']['days'];

						// Initializing delivery address for message
						$delivery_address = $cart->buffer['delivery']['location']['name'] . ', ' . $cart->buffer['delivery']['street'];

						$ctx->sendMessage(
							<<<TXT
							🛒 *Добавлена корзина \#$identifier*

							$list
							*Стоимость:* $cost$symbol \+ $delivery_cost$symbol \($delivery_days дней\)
							*Адрес доставки:* $delivery_address
							TXT
						)->then(function ($message)  use ($ctx, $account, $cart) {
							// Sended the message

							// Writing to the runtime buffer
							$ctx->setUserDataItem('cart', $cart);

							if (empty($account->receiver['sim']) || empty($account->receiver['name'])) {
								// Not registered account

								$ctx->sendMessage(
									<<<TXT
									⚠️ *Необходимо завершить регистрацию для продолжения*
									TXT
								)->then(function ($message) use ($ctx) {
									// Sended message

									// Sending account parameters menu
									static::account_parameters($ctx);
								});
							} else {
								// Registered account

								$ctx->sendMessage(
									<<<TXT
									🛡 *Все проверки пройдены*
									TXT
								)->then(function ($message) use ($ctx) {
									// Sended message

									// Sending order request
									static::order_request($ctx);
								});
							}
						});
					}

					// Deinitializing unnecessary variables
					unset($cart, $list);
				}
			}

			// Deinitializing unnecessary variables
			unset($cart);
		}

		// Deinitializing unnecessary variables
		unset($account);
	}

	/**
	 * Order request
	 *
	 * @param context $ctx
	 *
	 * @return void
	 */
	public static function order_request(context $ctx): void
	{
		// Initializing the account
		$account = $ctx->get('account');

		if ($account) {
			// Initialized the account

			$ctx->getUserDataItem('cart')->then(function ($cart) use ($ctx) {
				// Readed the cart from the session buffer

				if (!empty($cart)) {
					// Initialized the cart

					// Initializing identifier of the cart
					$identifier = $cart->getKey();

					$ctx->sendMessage(
						<<<TXT
						🛒 *Корзина \#$identifier*
						TXT,
						[
							'reply_markup' => [
								'inline_keyboard' => [
									[
										['text' => '📦 Оформить заказ', 'callback_data' => 'order'],
									],
									[
										['text' => '⚡ Помощь с заказом', 'url' => 'https://t.me/iarming'],
									]
								],
								'disable_notification' => true
							]
						]
					);
				}
			});
		}

		// Deinitializing unnecessary variables
		unset($account);
	}

	/**
	 * Order request
	 *
	 * @param context $ctx
	 *
	 * @return void
	 */
	public static function order(context $ctx): void
	{
		// Initializing account
		$account = $ctx->get('account');

		if ($account) {
			// Initialized the account

			var_dump($ctx->getCbData());
			die;

			// Initializing cart
			$cart = cart::_read(
				filter: 'd.share == @share',
				sort: 'd.updated DESC, d.created DESC, d._key DESC',
				amount: 1,
				page: 1,
				parameters: ['share' => $share]
			);

			// Deinitializing unnecessary variables
			unset($share);

			// Unsharing the cart
			$cart->unshare();

			if ($cart instanceof cart) {
				// Initialized the cart

				// Connecting the cart to the account
				$edge = $account->connect($cart);

				if (!empty($edge)) {
					// Connected the cart to the account

					// Initializing products in the cart
					$products = $cart->products(language: $account->language ?? language::ru, currency: $account->currency ?? currency::rub);

					if (!empty($products)) {
						// Initialized products in the cart

						// Declaring total cost of products
						$cost = 0;

						// Declaring formatted list of products for message
						$list = '';

						// Initializing iterator of rows
						$row = 0;

						foreach ($products as $product) {
							// Iterating over products

							// Generating formatted list of products for message
							$list .= static::unmarkdown(++$row . '. ' . $product['document']['name'] . ' (' . $product['amount'] . 'шт)') . "\n";

							// Generating total cost of products
							$cost += $product['document']['cost'] * $product['amount'];
						}

						// Deinitializing unnecessary variables
						unset($products, $product, $row);

						// Initializing currency symbol
						$symbol = ($account->currency ?? currency::rub)->symbol();

						// Initializing delivery cost for message
						$delivery_cost = $cart->buffer['delivery']['cost'];

						// Initializing delivery days for message
						$delivery_days = $cart->buffer['delivery']['days'];

						// Initializing delivery address for message
						$delivery_address = $cart->buffer['delivery']['location']['name'] . ', ' . $cart->buffer['delivery']['street'];

						// Deinitializing unnecessary variables
						unset($cart);

						$ctx->sendMessage(
							<<<TXT
							🛒 *Добавлена корзина*

							$list
							*Стоимость:* $cost$symbol \+ $delivery_cost$symbol \($delivery_days дней\)
							*Адрес доставки:* $delivery_address
							TXT,
							[
								'reply_markup' => [
									'inline_keyboard' => [
										[
											/* ['text' => '🧾 Оплатить', 'web_app' => ['url' => 'https://telegram.arming.ru/']] */
											/* ['text' => '📦 Оформить заказ', 'url' => 'https://auth.robokassa.ru/Merchant/Index.aspx?MerchantLogin=demo&OutSum=11&Description=Покупка в демо магазине&SignatureValue=2c113e992e2c985e43e348ff3c12f32b'], */
											['text' => '📦 Оформить заказ', 'callback_data' => 'order'],
										]
									],
									'disable_notification' => true
								]
							]
						);
					}

					// Deinitializing unnecessary variables
					unset($cart, $list);
				}
			}

			// Deinitializing unnecessary variables
			unset($cart);
		}

		// Deinitializing unnecessary variables
		unset($account);
	}

	/**
	 * Account parameters
	 *
	 * Menu for request parameters for the account
	 *
	 * @param context $ctx
	 *
	 * @return void
	 */
	public static function account_parameters(context $ctx): void
	{
		// Initializing the account
		$account = $ctx->get('account');

		if ($account) {
			// Initialized the account

			$ctx->getUserDataItem('cart')
				->then(
					function ($cart) use ($ctx, $account) {
						// Readed the cart from the session buffer

						if (!empty($cart) && !empty($account->receiver['sim']) && !empty($account->receiver['name'])) {
							// Found process for the cart offering and initialized all required account parameters

							// Sending the menu of requesting order
							static::order_request($ctx);
						} else {
							// Not found process for the cart offering or not initialized all required account parameters

							$ctx->sendMessage(
								<<<TXT
								📑 *Настройка параметров получателя*
								TXT,
								[
									'reply_markup' => [
										'inline_keyboard' => [
											[
												['text' => (empty($account->receiver['sim']) ? '🔴' : '🟢') . ' SIM-номер получателя', 'callback_data' => 'receiver_sim_choose']
											],
											[
												['text' => (empty($account->receiver['name']) ? '🔴' : '🟢') . ' Имя получателя', 'callback_data' => 'receiver_name_choose'],
											]
										],
										'disable_notification' => true,
									]
								]
							);
						}
					}
				);
		}

		// Deinitializing unnecessary variables
		unset($account);
	}

	/**
	 * Receiver SIM-number
	 *
	 * Request the receiver SIM-number and write into account
	 *
	 * @param context $ctx
	 *
	 * @return void
	 */
	public static function receiver_sim_choose(context $ctx): void
	{
		// Initializing account
		$account = $ctx->get('account');

		if ($account) {
			// Initialized the account

			// Sending the message
			$ctx->sendMessage(
				<<<TXT
				📞 *SIM\-номер получателя*

				Используется для генерации договора с компанией осуществляющией доставку товаров из магазина
				TXT,
				[
					'reply_markup' => [
						'keyboard' => [
							[
								['text' => '📂 Использовать номер аккаунта', 'request_contact' => true]
							],
						],
						'disable_notification' => true
					]
				]
			)->then(function ($message) use ($ctx) {
				// Sended the message

				// Sending the message
				$ctx->sendMessage(
					<<<TXT
					Если SIM\-номер *отличается* от привязанного к аккаунту, то введите его вручную
					TXT,
					[
						'reply_markup' => [
							'inline_keyboard' => [
								[
									['text' => '✏️ Ввести вручную', 'callback_data' => 'receiver_sim_request']
								],
							],
							'disable_notification' => true,
						]
					]
				);
			});
		}

		// Deinitializing unnecessary variables
		unset($account);
	}

	/**
	 * Receiver SIM-number request
	 *
	 * Request SIM-number
	 *
	 * @param context $ctx
	 *
	 * @return void
	 */
	public static function receiver_sim_request(context $ctx): void
	{
		// Initializing account
		$account = $ctx->get('account');

		if ($account) {
			// Initialized the account

			$ctx->sendMessage(
				<<<TXT
				📞 *Пришлите SIM\-номер получателя*

				*Пример:* 79099995522
				TXT,
				[
					'reply_markup' => [
						'disable_notification' => true,
						'remove_keyboard' => true
					]
				]
			)->then(function ($message) use ($ctx) {
				// Sended message

				$ctx->nextStep([static::class, 'receiver_sim_input'], true);
			});
		}

		// Deinitializing unnecessary variables
		unset($account);
	}

	/**
	 * Receiver SIM-number from input
	 *
	 * Receive SIM-number from message
	 *
	 * @param context $ctx
	 *
	 * @return void
	 */
	public static function receiver_sim_input(context $ctx): void
	{
		// Initializing account
		$account = $ctx->get('account');

		if ($account) {
			// Initialized the account

			// Initializing received text (SIM-number)
			$text = $ctx->getMessage()?->getText();

			if (!empty($text)) {
				// Initialized received text (SIM-number)

				// Sanitizing received text (only numbers)
				$sanitized = preg_replace('/[^\d]/', '', $text);

				if (!empty($sanitized)) {
					// Initialized sanitized received text (only numbers)

					if (strlen($sanitized) > 6) {
						// Length of received SIM-number is more than 6 symbols

						if (strlen($sanitized) < 20) {
							// Length of received SIM-number is less than 20 symbols

							// Writing to the buffer
							$ctx->setUserDataItem('receiver_sim', $sanitized);

							$ctx->sendMessage(
								<<<TXT
						📞 *SIM\-номер:* $sanitized
						TXT,
								[
									'reply_markup' => [
										'inline_keyboard' => [
											[
												['text' => '✅ Сохранить', 'callback_data' => 'receiver_sim_write'],
												['text' => '❎ Отменить', 'callback_data' => 'receiver_sim_choose']
											]
										],
										'disable_notification' => true
									]
								]
							);

							// Resetting the buffer
							$ctx->endConversation();
						} else {
							// Length of received SIM-number is NOT less than 20 symbols

							// Sending the message
							$ctx->sendMessage('⚠️ *SIM\-номер должен быть короче 20\-ти символов*');
						}
					} else {
						// Length of received SIM-number is NOT more than 6 symbols

						// Sending the message
						$ctx->sendMessage('⚠️ *SIM\-номер должен быть длиннее 3\-х символов*');
					}
				}
			}
		}

		// Deinitializing unnecessary variables
		unset($account);
	}

	/**
	 * Receiver SIM-number write
	 *
	 * Write received and accepted receiver SIM-number into account
	 *
	 * @param context $ctx
	 *
	 * @return void
	 */
	public static function receiver_sim_write(context $ctx): void
	{
		// initializing account
		$account = $ctx->get('account');

		if ($account) {
			// initialized the account

			$ctx->getUserDataItem('receiver_sim')->then(function ($sim) use ($ctx, $account) {
				// Initialized receiver SIM-number

				if (!empty($sim)) {
					// Initialized receiver SIM-number

					// Writing receiver SIM-number into the account
					$account->receiver = ['sim' => (int) $sim] + ($account->receiver ?? []);

					// Deabstracting the language parameter
					$account->language = $account->language->name;

					if (document::update($account->__document())) {
						// Writed the account instance into the ArangoDB document

						$ctx->sendMessage(
							<<<TXT
							✅ *SIM\-номер зарегистрирован:* $sim
							TXT,
							[
								'reply_markup' => [
									'disable_notification' => true,
									'remove_keyboard' => true
								]
							]
						)->then(function ($message) use ($ctx) {
							// Sended message

							// Deinitializing receiver SIM-number
							$ctx->setUserDataItem('receiver_sim', null);

							// Sending the account parameters menu
							static::account_parameters($ctx);
						});
					} else {
						// Not writed the account instance into the ArangoDB document

						// Sending the message
						$ctx->sendMessage('⚠️ *Не удалось записать SIM\-номер*');
					}
				} else {
					// Not initialized receiver SIM-number

					// Sending the message
					$ctx->sendMessage('⚠️ *Ошибка при регистрации SIM\-номера*');
				}
			});
		}

		// Deinitializing unnecessary variables
		unset($account);
	}

	/**
	 * Receiver name
	 *
	 * Request the receiver name and write into account
	 *
	 * @param context $ctx
	 *
	 * @return void
	 */
	public static function receiver_name_choose(context $ctx): void
	{
		// Initializing account
		$account = $ctx->get('account');

		if ($account) {
			// Initialized the account

			// Sending the message
			$ctx->sendMessage(
				<<<TXT
				📞 *ФИО получателя*

				Используется для генерации договора с компанией осуществляющией доставку товаров из магазина
				TXT,
				[
					'reply_markup' => [
						'inline_keyboard' => [
							[
								['text' => '✏️ Ввести вручную', 'callback_data' => 'receiver_name_request']
							],
						],
						'disable_notification' => true,
					]
				]
			);
		}

		// Deinitializing unnecessary variables
		unset($account);
	}

	/**
	 * Receiver name request
	 *
	 * Request name
	 *
	 * @param context $ctx
	 *
	 * @return void
	 */
	public static function receiver_name_request(context $ctx): void
	{
		// Initializing account
		$account = $ctx->get('account');

		if ($account) {
			// Initialized the account

			$ctx->sendMessage(
				<<<TXT
				📞 *Пришлите ФИО получателя*

				*Пример:* Иван Иванов Иванович
				TXT,
				[
					'reply_markup' => [
						'disable_notification' => true,
						'remove_keyboard' => true
					]
				]
			)->then(function ($message) use ($ctx) {
				// Sended message

				$ctx->nextStep([static::class, 'receiver_name_input'], true);
			});
		}

		// Deinitializing unnecessary variables
		unset($account);
	}

	/**
	 * Receiver name from input
	 *
	 * Receive name from message
	 *
	 * @param context $ctx
	 *
	 * @return void
	 */
	public static function receiver_name_input(context $ctx): void
	{
		// Initializing account
		$account = $ctx->get('account');

		if ($account) {
			// Initialized the account

			// Initializing received text (name)
			$text = $ctx->getMessage()?->getText();

			if (!empty($text)) {
				// Initialized received text (name)

				// Sanitizing received text (only numbers)
				$sanitized = static::unmarkdown(preg_replace('/[^\s\w\-]/u', '', $text));

				if (!empty($sanitized)) {
					// Initialized sanitized received text (only numbers)

					if (mb_strlen($sanitized) > 3) {
						// Length of received name is more than 3 symbols

						if (mb_strlen($sanitized) < 256) {
							// Length of received name is less than 256 symbols

							// Writing to the buffer
							$ctx->setUserDataItem('receiver_name', $sanitized);

							$ctx->sendMessage(
								<<<TXT
								🪪 *ФИО:* $sanitized
								TXT,
								[
									'reply_markup' => [
										'inline_keyboard' => [
											[
												['text' => '✅ Сохранить', 'callback_data' => 'receiver_name_write'],
												['text' => '❎ Отменить', 'callback_data' => 'receiver_name_choose']
											]
										],
										'disable_notification' => true
									]
								]
							);

							// Resetting the buffer
							$ctx->endConversation();
						} else {
							// Length of received name is NOT less than 20 symbols

							// Sending the message
							$ctx->sendMessage('⚠️ *ФИО должны быть короче 256\-ти символов*');
						}
					} else {
						// Length of received name is NOT more than 6 symbols

						// Sending the message
						$ctx->sendMessage('⚠️ *ФИО должны быть длиннее 3\-х символов*');
					}
				}
			}
		}

		// Deinitializing unnecessary variables
		unset($account);
	}

	/**
	 * Receiver name write
	 *
	 * Write received and accepted receiver name into account
	 *
	 * @param context $ctx
	 *
	 * @return void
	 */
	public static function receiver_name_write(context $ctx): void
	{
		// initializing account
		$account = $ctx->get('account');

		if ($account) {
			// initialized the account

			$ctx->getUserDataItem('receiver_name')->then(function ($name) use ($ctx, $account) {
				// Initialized receiver name

				if (!empty($name)) {
					// Initialized receiver name

					// Writing receiver name into the account
					$account->receiver = ['name' => $name] + ($account->receiver ?? []);

					// Deabstracting the language parameter
					$account->language = $account->language->name;

					if (document::update($account->__document())) {
						// Writed the account instance into the ArangoDB document

						$ctx->sendMessage(
							<<<TXT
							✅ *ФИО зарегистрированы:* 
							$name
							TXT,
							[
								'reply_markup' => [
									'disable_notification' => true,
									'remove_keyboard' => true
								]
							]
						)->then(function ($message) use ($ctx) {
							// Sended message

							// Deinitializing receiver name
							$ctx->setUserDataItem('receiver_name', null);

							// Sending the account parameters menu
							static::account_parameters($ctx);
						});
					} else {
						// Not writed the account instance into the ArangoDB document

						// Sending the message
						$ctx->sendMessage('⚠️ *Не удалось записать ФИО*');
					}
				} else {
					// Not initialized receiver name

					// Sending the message
					$ctx->sendMessage('⚠️ *Ошибка при регистрации ФИО*');
				}
			});
		}

		// Deinitializing unnecessary variables
		unset($account);
	}
}
