<?php

declare(strict_types=1);

namespace mirzaev\arming_bot\models;

// Files of the project
use mirzaev\arming_bot\models\core,
	mirzaev\arming_bot\controllers\core as controller,
	mirzaev\arming_bot\models\catalog,
	mirzaev\arming_bot\models\suspension,
	mirzaev\arming_bot\models\account;

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

/**
 * Model of chat (telegram)
 *
 * @package mirzaev\arming_bot\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
	{
		// Инициализация клавиатуры
		$keyboard = [
			[
				['text' => '🛒 Каталог', 'web_app' => ['url' => 'https://arming.dev.mirzaev.sexy']]
			],
			[
				['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' => '⚡ Связь с менеджером', 'url' => 'https://git.mirzaev.sexy/mirzaev/mashtrash'],
					['text' => '📨 Почта', 'text' => ''],
				],
				[
					['text' => '🪖 Сайт', 'url' => '']
					['text' => '🛒 Wildberries', 'url' => '']
				]
			]
		],
		'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 ?? 'en'
									);

									// Отправка сообщения
									$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);
		}
	}
}
