<?php

declare(strict_types=1);

namespace Legacy\Utility;

use erp\modules\Notification\Application\Exception\NotificationProcessingError;
use erp\modules\Notification\Application\UseCase\Command\CreateNotification\CreateNotificationCommand;
use erp\modules\Notification\Application\UseCase\Command\CreateNotification\CreateNotificationHandler;
use erp\modules\Notification\Domain\Entity\Notification;
use erp\modules\Notification\Infrastructure\Exception\ServiceClassNotRegisteredException;
use erp\modules\Staff\models\Employee;
use Exception;
use InvalidArgumentException;
use Legacy\CronAR;
use Legacy\CustomerAR;
use Legacy\Html\SettingsNotificationHtml;
use Legacy\ReadModel\Dto\EmployeePropertyDto;
use Legacy\ReadModel\Dto\MessageTemplateDto;
use Legacy\ReadModel\Dto\NotificationSourceDto;
use Legacy\ReadModel\Fetcher\EmployeePropertyFetcher;
use Legacy\ReadModel\System\EmployeeActionLogSystem;
use Legacy\ReadModel\System\EmployeePropertySystem;
use Legacy\ReadModel\System\MessageTemplateSystem;
use Legacy\ReadModel\System\NotificationSourceSystem;
use Legacy\ReadModel\System\NotificationTaskSystem;
use Legacy\ReadModel\System\SettingSystem;
use Legacy\TaskAR;
use Legacy\YiiUtility\Notifications;
use Legacy\YiiUtility\SettingsExternal;
use Yii;
use yii\base\InvalidConfigException;
use yii\di\NotInstantiableException;

class Mail
{
	public static int $isMailTest = 0;

	public static function smtp_robot($connection): array
	{
		$buffer = '';

		$lastId = SettingSystem::getByNameString(SettingsCatalog::J_ROBOT_INBOX_LASTID);

		$arrayReturn = self::smtp_command($connection, "STAT");
		$buffer .= 'STAT - RET: ' . $arrayReturn['STR'];
		if (2 === self::$isMailTest) {
			$buffer .= $arrayReturn['BUFER'];
		}
		$returnPage = $arrayReturn['RET'];
		$returnPage = self::smtp_replace($returnPage);

		$arrayMail = [];

		if ('' !== $returnPage) {
			$array1 = explode(' ', $returnPage);
			$listCount = $array1[0];

			if ($listCount < 1 && !empty($lastId)) {
				$buffer .= "DELETE COUNTER\n";
				SettingSystem::setByName(SettingsCatalog::J_ROBOT_INBOX_LASTID, '');
			}

			$buffer .= "LAST ID: " . $lastId . "\n";

			for ($j = $listCount; $j >= 1; $j--) {
				$returnPage = self::smtp_command($connection, "TOP " . $j . " 10");
				$returnPage = $returnPage['RET'];
				if (self::$isMailTest === 2) {
					$buffer .= $returnPage['BUFER'];
				}

				$array1 = explode("Message-ID: ", $returnPage);
				if (!isset($array1[1])) {
					$array1[1] = '';
				}
				$array1 = explode("\r\n", $array1[1]);
				$tempId = $array1[0];

				if (empty($tempId)) {
					$array1 = explode("Message-Id: ", $returnPage);
					if (!isset($array1[1])) {
						$array1[1] = '';
					}
					$array1 = explode("\r\n", $array1[1]);
					$tempId = $array1[0];
				}

				$tempId = str_replace(['<', '>'], '', $tempId);

				if (!empty($tempId) && $tempId === $lastId) {
					break;
				}

				if (empty($lastId) || (!empty($tempId) && $tempId !== $lastId)) {
					if ($j === $listCount) {
						SettingSystem::setByName(SettingsCatalog::J_ROBOT_INBOX_LASTID, $tempId);
					}

					$arrayReturn = self::smtp_command($connection, "RETR " . $j);
					$buffer .= 'RETR ' . $j . ' - RET: ' . $arrayReturn['STR'] . "\n";
					if (self::$isMailTest === 2) {
						$buffer .= $arrayReturn['BUFER'];
					}
					$raw = $arrayReturn['RET'];
					$returnPage = (string)$arrayReturn['RET'];
					$returnPage = str_replace('To:From:Subject:Message', 'To_:From_:Subject_:Message', $returnPage);

					$array1 = explode("From: ", $returnPage);
					if (isset($array1[1])) {
						$tempArray = explode("To: ", $array1[1]);
						$array1[1] = $tempArray[0];
					}

					if (!isset($array1[1])) {
						$array1[1] = '';
					}

					if (0 < self::$isMailTest) {
						$buffer .= "DEBUG From1-0: |" . $array1[1] . "|\n";
					}

					$array1[1] = str_replace("\r\n", ' ', $array1[1]);
					$array1[1] = str_replace("\n", ' ', (string)$array1[1]);
					$array1[1] = str_replace("\r", ' ', (string)$array1[1]);
					$from = $array1[1];
					if (0 < self::$isMailTest) {
						$buffer .= "DEBUG From1-1: " . $from . "\n";
					}

					$array1 = explode("<", $from);
					if (isset($array1[1])) {
						$from = str_replace('>', '', $array1[1]);
						if (0 < self::$isMailTest) {
							$buffer .= "DEBUG From2: " . $from . "\n";
						}
					}

					if (0 < self::$isMailTest) {
						echo "From: " . $from . "\n";
						$buffer .= "DEBUG From3: " . $from . "\n";
					}

					$array = explode(' ', $from);
					$from = $array[0];

					if (0 < self::$isMailTest) {
						$buffer .= "DEBUG From4: " . $from . "\n";
					}

					$subject = '';
					$array1 = explode("Subject: ", $returnPage);
					if (isset($array1[1])) {
						if (0 < self::$isMailTest) {
							$buffer .= "DEBUG Subject-R: " . $array1[1] . "\n";
						}

						$array1 = explode(":", $array1[1]);
						$array1 = explode("\r\n", $array1[0]);
						for ($y = 0; $y <= (count($array1) - 2); ++$y) {
							if (0 < self::$isMailTest) {
								$buffer .= "DEBUG Subject (" . $y . "): " . $array1[$y] . "\n";
							}

							$subject .= self::smtp_subject($array1[$y]);
						}
						if (0 < self::$isMailTest) {
							echo "Subject: " . $subject . "\n";

							$buffer .= "DEBUG Subject: " . $subject . "\n";
						}
					}

					$array1 = explode("Date: ", $returnPage);
					$array1 = explode("\r\n", $array1[1]);
					$date = $array1[0];
					if (0 < self::$isMailTest) {
						echo "Date: " . $date . "\n";
					}

					$body = '';
					$previousBody = '';
					$previousEncode = '';
					$array1 = explode("Content-Type: ", $returnPage);
					for ($y = 1; $y <= (count($array1) - 1); ++$y) {
						$array2 = explode("\r\n", $array1[$y]);
						$array3 = explode(";", $array2[0]);
						if (!isset($array3[1])) {
							$array3[1] = '';
						}

						$contentType = strtolower($array3[0]);
						if (0 < self::$isMailTest) {
							echo "Content-type: " . $contentType . "\n";
						}
						if ('text/plain' === $contentType || 'text/html' === $contentType) {
							$cp = strtoupper(trim(str_ireplace('charset=', '', $array3[1])));
							$contentBody = $array1[$y];

							if (0 < self::$isMailTest) {
								$buffer .= "DEBUG BODY0: " . $contentBody . "\n";
							}

							$array4 = explode("Content-Transfer-Encoding: ", $contentBody);
							if (!isset($array4[1])) {
								$array4[1] = '';
							}

							if (isset($array4[1])) {
								$encode = $array4[1];
								$encode = explode("\r\n", $encode);
								$encode = strtolower($encode[0]);
							} else {
								$encode = '';
								if ('' !== $previousEncode) {
									$encode = $previousEncode;
								}
							}

							$previousEncode = $encode;

							$tempPosition = strpos($contentBody, "\r\n\r\n");
							$contentBody = substr($contentBody, $tempPosition + 4, (int)mb_strlen($contentBody));

							$tempPosition = strpos($contentBody, "\r\n---------");
							if (0 >= $tempPosition) {
								$tempPosition = strpos($contentBody, "\r\n.\r\n");
								if (0 >= $tempPosition) {
									$tempPosition = strpos($contentBody, "\r\n\r\n");
								}
							}
							$contentBody = substr($contentBody, 0, (int)$tempPosition);
							$contentBodyOld = $contentBody;

							$body = self::smtp_body($contentBody, $cp, $encode);

							if (0 < self::$isMailTest) {
								$buffer .= "DEBUG BODY1: " . $body . "\n";
							}

							if ('text/plain' === $contentType && '' === $previousBody) {

								$previousBody = $body;
							}

							if (0 < self::$isMailTest) {
								echo 'Content-Type ' . $y . '|' . $contentType . '|' . $cp . "|" . $encode . "|\n";
								echo '*** MAIL 1 *** ' . $body . "|\n";
								echo "=========================================================\n";
								echo '*** MAIL 2 *** ' . $contentBody . "|\n";
								echo "=========================================================\n";
								echo $array1[$y] . "|\n";
								echo "=========================================================\n";
								echo $contentBodyOld . "|\n";
								echo "=========================================================\n\n\n";
							}
						} elseif ('' === $body) {
							$body = 'UNKNOWN';
						}
					}

					$date = strtotime($date);
					$date = date('d.m.Y H:i:s', $date);

					$isChange = 0;
					if ('' !== $previousBody) {
						$body = $previousBody;
						$isChange = 1;
					}

					$arrayMail[] = [
						'ID'       => $tempId,
						'FROM'     => $from,
						'SUBJ'     => $subject,
						'BODY'     => $body,
						'DATE'     => $date,
						'RAW'      => $raw,
						'ISCHANGE' => $isChange,
					];

				}

			}

		}

		return [
			'LIST'  => $arrayMail,
			'BUFER' => $buffer,
		];
	}

	public static function smtp_command($connection, $command): array
	{
		fwrite($connection, $command . "\r\n");
		$bufer = '';
		if (0 < self::$isMailTest) {
			echo "COMMAND: " . $command . "\n";
		}
		$bufer .= "COMMAND: " . $command . "\n";
		if (
			str_starts_with((string)$command, 'TOP')
			||
			str_starts_with((string)$command, 'RETR')
		) {
			$read = fgets($connection);
			$bufer .= "read: " . $read . "\n";
			$string = $read;
			$line = $read;
			if (0 < self::$isMailTest) {
				echo "RETURN: " . $line . "\n";
			}
			if (!str_starts_with((string)$line, '-ERR ')) {
				while (!preg_match("/^\.\r\n/", $line)) {
					$line = fgets($connection);
					$bufer .= "line: " . $line . "\n";
					$read .= $line;
				}
			} else {
				$read = '';
			}
			$returnPage = $read;
		} else {
			$returnPage = fgets($connection);
			$bufer .= "ret: " . $returnPage . "\n";
			$string = str_replace("\n", '', str_replace("\r", '', (string)$returnPage)) . "\n";

		}
		$arrayResult = [
			'RET'   => $returnPage,
			'STR'   => $string,
			'BUFER' => $bufer,
		];
		if (0 < self::$isMailTest) {
			echo "RETURN: " . $returnPage . "\n";
		}
		return $arrayResult;
	}

	public static function smtp_replace($string): string
	{
		if (str_starts_with((string)$string, '+OK')) {
			$string = str_replace('+OK', '', (string)$string);
			$string = trim($string);
		} else {
			$string = '';
		}
		return $string;
	}

	public static function smtp_subject($subject)
	{
		$array1 = explode('?', $subject);
		if (isset($array1[1])) {

			$cp = strtoupper($array1[1]);
			[$typeId, $text] = [$array1[2], $array1[3]];
			if ('B' === $typeId) {
				$text = base64_decode($text);
			} else {
				$text = quoted_printable_decode($text);
			}

			$subjectReal = $text;
			if ('WINDOWS-1251' === $cp) {
				$subjectReal = iconv($cp, "UTF-8", $subjectReal);
			}
			$subject = $subjectReal;
		}
		return $subject;
	}

	public static function smtp_body($text, $cp, $encode)
	{

		$cp = str_replace('"', '', (string)$cp);
		if ('base64' === $encode) {
			$text = base64_decode($text);
		}
		if ('quoted-printable' === $encode) {
			$text = quoted_printable_decode($text);
		}

		$textReal = $text;
		if ('KOI8-R' === $cp) {
			$textReal = iconv($cp, "UTF-8", $textReal);
		}
		if ('WINDOWS-1251' === $cp) {
			$textReal = iconv($cp, "UTF-8", $textReal);
		}
		return $textReal;
	}

	public static function reload_lang_to_mail($mail): string
	{
		if (NULL === $mail) {
			$mail = 'empty';
		}
		$mail = strtolower($mail);

		$employeePropertyDto = Yii::$container
			->get(EmployeePropertyFetcher::class)
			->getOneByCondition(
				['ILIKE', EmployeePropertyDto::F_EMAIL, $mail]
			);

		if ($employeePropertyDto) {
			$language = Localization::langNameToOld(Employee::findOne($employeePropertyDto->employee_id)->language);
		} else {
			$language = '';
		}
		if ('' === $language) {
			$language = SettingSystem::getByNameString(SettingsCatalog::MAIN_LANG);
		}
		if ('' === $language) {
			$language = 'ru';
		}
		if ('' !== $language && $language !== Central::$language) {
			Central::$language = $language;
		}
		return $language;
	}

	public static function sendAllTransportNotifyToEmployee(
		array    $notificationSetting,
		int      $employeeId,
		string   $templateName,
		int|null $taskId = NULL,
		int      $isAlwaysSendSms = 0,
		int      $employeeInitiatorId = 0,
		int      $newStateId = 0,
	): void
	{
		$task = TaskAR::findOne($taskId);
		if (TRUE !== TaskAR::isSendForTaskCheckClose($task->getTaskStatusId())) {
			return;
		}

		$employee = Employee::findOne($employeeId);
		if (!$employee) {
			throw new InvalidArgumentException(
				__CLASS__ . ' | ' . __FUNCTION__ . ' | Employee #' . $employeeId . ' not found'
			);
		}

		$legacyEmployee = EmployeePropertySystem::getLegacyEmployee($employeeId);

		$langTemp = Localization::langNameToOld($employee->language);

		if (
			isset($notificationSetting[Notification::METHOD_EMAIL])
			&&
			'' !== $legacyEmployee[EmployeePropertyDto::F_EMAIL]
		) {
			[$body, $subject, $options] = MessageTemplateSystem::taskTemplateInfoById(
				taskId:       $taskId,
				method:       Notification::METHOD_EMAIL,
				templateName: $templateName,
				lang:         $langTemp,
				newStateId:   $newStateId,
			);
			if ('' !== $subject) {
				self::sendToEmployee(
					employeeId: $employeeId,
					subject:    $subject,
					body:       $body,
					options:    $options
				);
			}
		}

		if (
			isset($notificationSetting[Notification::METHOD_SMS])
			||
			1 === $isAlwaysSendSms
		) {
			$phone = $legacyEmployee[EmployeePropertyDto::F_PHONE];
			if ('' !== $phone) {
				[$body] = MessageTemplateSystem::taskTemplateInfoById(
					taskId:       $taskId,
					method:       Notification::METHOD_SMS,
					templateName: $templateName,
					lang:         Central::$language,
					newStateId:   $newStateId,
				);
				if ('' !== $body) {
					Sms::send(
						sourceType: NotificationSourceDto::SOURCE_TYPE_TASK_EMPLOYEE,
						customerId: 0,
						number:     $phone,
						message:    $body,
						employeeId: $employeeInitiatorId,
						arg1:       NotificationSourceDto::ARG_TASK,
						arg2:       $taskId
					);
				}
			}
		}

		if (
			isset($notificationSetting[Notification::METHOD_CUSTOM])
			&&
			'' !== $legacyEmployee[EmployeePropertyDto::F_CUSTOM_HTTP_ADDRESS]
			&&
			TRUE === $legacyEmployee[EmployeePropertyDto::F_IS_WORKED]
		) {
			[$body] = MessageTemplateSystem::taskTemplateInfoById(
				taskId:       $taskId,
				method:       Notification::METHOD_CUSTOM,
				templateName: $templateName,
				lang:         $langTemp,
				newStateId:   $newStateId,
			);
			if ('' !== $body) {
				self::sendToMessenger(
					serviceMethod: Notification::METHOD_CUSTOM,
					recipient:     $legacyEmployee[EmployeePropertyDto::F_CUSTOM_HTTP_ADDRESS],
					body:          $body,
					arg1:          NotificationSourceDto::ARG_TASK,
					arg2:          $taskId,

				);
			}
		}

		if (isset($notificationSetting[Notification::METHOD_MESSENGER])) {
			$receiver = EmployeePropertySystem::getMessengerById($employeeId);
			if ('' !== $receiver) {
				[$body] = MessageTemplateSystem::taskTemplateInfoById(
					taskId:       $taskId,
					method:       Notification::METHOD_MESSENGER,
					templateName: $templateName,
					lang:         $langTemp,
					newStateId:   $newStateId,
				);
				if ('' !== $body) {
					self::sendToMessenger(
						serviceMethod: Notification::METHOD_MESSENGER,
						recipient:     $receiver,
						body:          $body,
						arg1:          NotificationSourceDto::ARG_TASK,
						arg2:          $taskId,
					);
				}
			}
		}
	}

	public static function sendToEmployee(
		int         $employeeId,
		string|null $subject,
		string      $body,
		array       $options = []
	): bool
	{
		$employee = Employee::findOne($employeeId);
		if (!$employee) {
			return FALSE;
		}
		$legacyEmployee = EmployeePropertySystem::getLegacyEmployee($employeeId);
		if ($legacyEmployee[EmployeePropertyDto::F_IS_WORKED] !== TRUE) {
			return FALSE;
		}
		if ('' === $legacyEmployee[EmployeePropertyDto::F_EMAIL]) {
			return FALSE;
		}

		$isHtml = FALSE;
		$format = $options[MessageTemplateDto::OPTION_FORMAT] ?? '';
		if ($format === MessageTemplateDto::OPTION_EMAIL_HTML) {
			$isHtml = TRUE;
		}

		self::sendMail(
			to:      $legacyEmployee[EmployeePropertyDto::F_EMAIL],
			subject: $subject,
			body:    $body,
			isHtml:  $isHtml
		);

		return TRUE;
	}

	public static function sendMail(
		string|null $to,
		string|null $subject,
		string      $body,
		bool        $isHtml = FALSE
	): bool
	{
		if (
			$to === NULL
			||
			$body === ''
		) {
			return FALSE;
		}
		$to = Central::replaceSymbolCode(trim($to));
		if ('' === $to) {
			return FALSE;
		}

		$body = Central::replaceSymbolCode(
			preg_replace("#(?<!\r)\n#i", "\r\n", $body)
		);

		$isEnabled = SettingsExternal::getValue('notifications/' . Notification::METHOD_EMAIL . '/enabled', TRUE);
		if ($isEnabled !== TRUE) {
			return FALSE;
		}

		$serviceName = Mail::getDefaultProfile(Notification::METHOD_EMAIL);
		if ((string)$serviceName === '') {
			return FALSE;
		}

		try {
			$command = new CreateNotificationCommand(
				method:      Notification::METHOD_EMAIL,
				profileName: $serviceName,
				address:     $to,
				message:     $body
			);
			if (!empty($subject)) {
				$command = $command->withSubject($subject);
			}
			if ($isHtml === TRUE) {
				$command = $command->withHtmlContent();
			}
			$handler = Yii::$container->get(CreateNotificationHandler::class);
			$handler->handle($command);
		} catch (Exception $e) {
			Central::logExceptionOnly($e);
			return FALSE;
		}

		return TRUE;
	}

	public static function getDefaultProfile(string $method): string
	{
		$defaultProfile = SettingsExternal::getValue(
			'notifications/' . $method . '/default_profile'
		);

		return $defaultProfile;
	}

	public static function sendToMessenger(
		string          $serviceMethod,
		string|null|int $recipient,
		string          $subject = '',
		string          $body = '',
		string          $sourceType = '',
		string          $arg1 = '',
		int             $arg2 = 0,
		bool            $isTest = FALSE
	): bool
	{
		if (is_int($recipient)) {
			$recipient = (string)$recipient;
		}
		if ($isTest === TRUE) {
			EmployeeActionLogSystem::writeLogWithZeroTypeId(
				actionTypeId: EmployeeHistoryType::T316,
				objectTypeId: 0,
				objectId:     0,
				objectName:   '',
				comment:      $recipient
			);
		}

		if (
			NULL === $recipient
			||
			'' === $recipient
			||
			NULL === $body
			||
			'' === $body
		) {
			return FALSE;
		}

		$subject = Central::replaceSymbolCode(
			preg_replace("#(?<!\r)\n#i", "\r\n", $subject)
		);

		if (
			$serviceMethod === Notification::METHOD_CUSTOM
			&&
			1 === SettingSystem::getByNameInt(SettingsCatalog::CUSTOM_HTTP_TRANSLIT)
		) {
			$body = Localization::rusToTranslit($body);
		}

		$serviceName = self::getDefaultProfile($serviceMethod);
		if ($serviceName === '') {
			return FALSE;
		}

		try {
			$command = new CreateNotificationCommand(
				method:      SettingsNotificationHtml::TYPE_NOTIFICATIONS[$serviceMethod]['method'],
				profileName: $serviceName,
				address:     Central::replaceSymbolCode($recipient),
				message:     $body
			);
			if (!empty($subject)) {
				$command = $command->withSubject($subject);
			}

			$handler = Yii::$container->get(CreateNotificationHandler::class);
			$notificationId = (int)$handler->handle($command);

			if ('' !== $sourceType) {
				NotificationSourceSystem::create($notificationId, $sourceType);
			}
			if (
				NotificationSourceDto::ARG_TASK === $arg1
				&&
				$arg2 > 0
			) {
				NotificationTaskSystem::create(
					notificationId: $notificationId,
					taskId:         $arg2
				);
			}
		} catch (Exception $e) {
			Central::logExceptionOnly($e);
			return FALSE;
		}

		return TRUE;
	}
}

/* cust:td:26D06A5F_sHGeLThQTVYQny4/BrpRnHe/hW7km4T/ */
