<?php

namespace App\Cron\Job;

/**
 * This class adds calendar events indicating expired (or about-to-expire) contracts (for suppliers/corporations).
 */
class ExpiredContractsAlert extends \App\Cron\Job\Utils\GeneralAbstract
{
	/**
	 * Cronjob category: {system|operational|financial|reporting}
	 * @var string
	 */
	protected $category = 'operational';


	public function getSettingsDialog(array $fields)
	{
		$form = parent::getSettingsDialog($fields);

		$_LANG = \App\Loader_Lang::getInstance()->getGlobal();

		$formContainer = \Engine\Form\Container\Fieldset::create();

		$form->addContainer($formContainer);

		$period = new \Engine\Form\Input\Text($_LANG['Admin']['CronJobs']['Management']['ExpiredContractsAlert']['options']['period'], 'period', $fields['settings']['period']);
		$period->setMandatory();
		$period->setStyle('width', 100);
		$period->setDetails($_LANG['Admin']['CronJobs']['Management']['ExpiredContractsAlert']['options']['periodTooltip']);
		$period->setValidator(['type'=>'int', 'minValue'=>0]);

		$formContainer->addElement($period);

		$formContainer->groupInputsInArray("settings");

		return $form;
	}


	protected function executeJob()
	{

		global $DBTCorporatesContracts, $DBTSuppliersContracts;

		$db = \DB::getInstance();

		// GET EXPIRE DATE (CURRENT DATE + PERIOD SET IN CRON CONFINGS)
		$this->getSettings();
		$period = $this->settings['period'] ? $this->settings['period'] : 7;

		$expireDateObj = new \Engine\DateTime();
		$expireDateObj->add(new \DateInterval("P{$period}D"));
		$expireDate = $expireDateObj->formatDateIso();

		$this->logger->info(sprintf('The expire date limit is `%s`.', $expireDate));

		// SQL
		$alertUsersContractsSQL="
			(
				SELECT
					`id`, `idResponsibleUser`,`serviceCode`,`contractNumber`,
					`contractDate`, `expireDate`, `idCorporate` AS `idCompany`,'client' AS `type`
				FROM `$DBTCorporatesContracts`
				WHERE `active`=1 AND `deleted`=0 AND `expireDate`!='0000-00-00' AND `expireDate`<'".$expireDate."'
			) UNION (
				SELECT
					`id`, `idResponsibleUser`,`serviceCode`,`contractNumber`,
					`contractDate`,`expireDate`,`idSupplier` AS `idCompany`,'supplier' AS `type`
				FROM `$DBTSuppliersContracts`
				WHERE `active`=1 AND `deleted`=0 AND `expireDate`!='0000-00-00' AND `idResponsibleUser`!=0 AND `expireDate`<'".$expireDate."'
			) ORDER BY `expireDate` ASC
		";
		$alertUsersContracts=$db->GetAll($alertUsersContractsSQL);

		// check SQL
		if ($db->ErrorNo()) {
			$this->logger->error('The list of contracts could not be generated due to a technical problem.');
			return;
		}

		// display contracts count
		if ($alertUsersContracts) {
			$this->logger->info(sprintf("Total number of contracts that have already expired or are about to expire until `%s`: %s.", $expireDate, count($alertUsersContracts)));
		}
		else {
			$this->logger->idle("No expired or about-to-expire contracts found.");
			return;
		}

		// ADD CALENDAR EVENTS ////////////////////////////////////////////////////////////////////
		$todayObj	= new \Engine\DateTime();
		$succCount 	= 0;
		foreach ($alertUsersContracts as $contractInfo) {

			$dateDiff = $todayObj->diff(\Engine\DateTime::createFromIsoDate($contractInfo['expireDate']));

			// get corporate or supplier alias
			if ($contractInfo['type']=="client"){
				$companyAlias = \Entity\Corporate::select($contractInfo['idCompany'])->alias;
			}
			else{
				$companyAlias = \Entity\Supplier::select($contractInfo['idCompany'])->alias;
			}

			// get service name
			if ($contractInfo['serviceCode']) {
				$serviceName = \App\Config\Services_Basic::getInstance()->getServiceName($contractInfo['serviceCode']);
			}
			else {
				$serviceName = '';
			}

			// compose description
			$thisDescription = "";
			if (!$dateDiff->days) {
				$thisDescription.="The {$contractInfo['type']} contract has expired today.";
			}
			elseif ($dateDiff->invert) {
				$thisDescription.="The {$contractInfo['type']} contract has expired for `{$dateDiff->days}` days.";
			}
			else {
				$thisDescription.="The {$contractInfo['type']} contract will expire in `{$dateDiff->days}` days.";
			}
			$thisDescription.="\r\n".ucfirst($contractInfo['type']).": ".$companyAlias.';';
			if ($contractInfo['serviceCode']) {
				$thisDescription.="\r\nService: ".$serviceName.';';
			}
			$thisDescription.="\r\nContract details: ".$contractInfo['contractNumber'].'/'.$contractInfo['contractDate'].'.';

			// ADD CALENDAR EVENT -----------------------------------------------------------------
			try {
				if ($contractInfo['type']=="client") {
					$alertUserId = $contractInfo['idResponsibleUser']?:\Entity\Corporate::select($contractInfo['idCompany'])->idAccountManager;
				}
				else {
					$alertUserId = $contractInfo['idResponsibleUser'];
				}

				if ($alertUserId) {
					$eventAdd = \Entity\CalendarEvent::insert();
					$eventAdd->title = "Auto event - expired contract";
					$eventAdd->description = $thisDescription;
					$eventAdd->allDay = false;
					$eventAdd->startDateTime = DATETIME;
					$eventAdd->endDateTime = DATETIME;
					$eventAdd->alertDateTime = date(DATETIME_FORMAT, TIMESTAMP - 300);
					$eventAdd->mailStatus = 1;
					$eventAdd->access = 'private';
					$eventAdd->idUser = $alertUserId;
					$eventAdd->idAddUser = 0;
					if ($contractInfo['type'] == "client") {
						$eventAdd->entities = [['type' => 'corporateContract', 'id' => $contractInfo['id']]];
					} else {
						$eventAdd->entities = [['type' => 'supplierContract', 'id' => $contractInfo['id']]];
					}
					$eventAdd->save();
					$succCount++;
				}
			} catch (\App\Entity\Exception $e) {
				$msg = 'A calendar event could not be added due to a technical problem:';
				foreach($e->getMessagesCollector()->getMessages() as $msgObj) {
					$msg.=$msgObj->getText().' ';
				}
				$msg.='Message description: '.str_replace("\r\n", ' ', $thisDescription);
				$this->logger->warning($msg);
			}

		}

		// display success message
		if ($succCount) {
			$this->logger->success(sprintf('%s calendar events were successfully added.', $succCount));
		}


	}


}