<?php

namespace App\Cron\Job;


class CorporateDueDateAlerts extends \App\Cron\Job\Utils\GeneralAbstract
{
	/**
	 * Cronjob category: {system|operational|financial|reporting}
	 * @var string
	 */
	protected $category = 'financial';


	private $invoiceStartDate;
	private $invoiceEndDate;

	public function __construct()
	{
		parent::__construct();
		$this->invoiceStartDate = date(MYSQL_FORMAT, strtotime("-6 months"));
		$this->invoiceEndDate = TODAY_ISO;
	}

	/**
	 * The method returns the form which is needed for the the current cronjob settings saving.
	 */
	public function getSettingsDialog(array $fields)
	{
		$form = parent::getSettingsDialog($fields);
		// remove email fieldset
		$form->traverseTreeForAllChilds(function($element) {
			if ($element instanceOf \Engine\Form\Container\Fieldset) {
				/* @var $element \Engine\Form\Container\Fieldset */
				if ($element->getName()=='errorManagement') {
					$element->getParent()->removeContainer($element);
				}
			}
		});

		$_LANG = \App\Loader_Lang::getInstance()->getGlobal();
		$form->setStyle('width', '200');

		$fieldset = \Engine\Form\Container\Fieldset::create($_LANG['Admin']['CronJobs']['Management']['CorporateDueDateAlerts']['editOptions']['fieldsets']['dueDates']);
		$form->addContainer($fieldset);

		$alertThresholdFld = \Engine\Form\Input\Text::create($_LANG['Admin']['CronJobs']['Management']['CorporateDueDateAlerts']['editOptions']['alertThreshold']['label'], 'alertThreshold', $fields['settings']['alertThreshold']);
		$alertThresholdFld->setCustomHTML($_LANG['Admin']['CronJobs']['Management']['CorporateDueDateAlerts']['editOptions']['alertThreshold']['daysAppend']);
		$alertThresholdFld->setStyle('width', '30');
		$alertThresholdFld->setTooltip($_LANG['Admin']['CronJobs']['Management']['CorporateDueDateAlerts']['editOptions']['alertThreshold']['tooltip']);
		$fieldset->addElement($alertThresholdFld);

		$paymentOverdueEmails = \Engine\Form\Input\Text::create($_LANG['Admin']['CronJobs']['Management']['CorporateDueDateAlerts']['editOptions']['paymentOverdueEmails']['label'], 'dueDateDue', $fields['settings']['dueDateDue']);
		$paymentOverdueEmails->setTooltip($_LANG['Admin']['CronJobs']['Management']['CorporateDueDateAlerts']['editOptions']['paymentOverdueEmails']['tooltip']);
		$fieldset->addElement($paymentOverdueEmails);

		$dueDateReachedEmails = \Engine\Form\Input\Text::create($_LANG['Admin']['CronJobs']['Management']['CorporateDueDateAlerts']['editOptions']['dueDateReachedEmails']['label'], 'dueDatePanic', $fields['settings']['dueDatePanic']);
		$dueDateReachedEmails->setTooltip($_LANG['Admin']['CronJobs']['Management']['CorporateDueDateAlerts']['editOptions']['dueDateReachedEmails']['tooltip']);
		$fieldset->addElement($dueDateReachedEmails);

		$dueDateAlertEmails = \Engine\Form\Input\Text::create($_LANG['Admin']['CronJobs']['Management']['CorporateDueDateAlerts']['editOptions']['dueDateAlertEmails']['label'], 'dueDateAlert', $fields['settings']['dueDateAlert']);
		$dueDateAlertEmails->setTooltip($_LANG['Admin']['CronJobs']['Management']['CorporateDueDateAlerts']['editOptions']['dueDateAlertEmails']['tooltip']);
		$fieldset->addElement($dueDateAlertEmails);

		$fieldset->groupInputsInArray("settings");

		return $form;
	}

	protected function executeJob()
	{
		$_LANG = \App\Loader_Lang::getInstance()->getGlobal();
		// SENDING EMAILS TO RECIPIENTS MENTIONED IN THE CRONJOB SETTINGS

		///////////////////////////////////////////////////////////////////////////////////////////////////
		// INITIAL CONFIGS ////////////////////////////////////////////////////////////////////////////////
		///////////////////////////////////////////////////////////////////////////////////////////////////

		$alertDaysLimit=$this->settings['alertThreshold'];
		if (is_numeric($alertDaysLimit) and $alertDaysLimit>=0) {
			$alertDate = date(MYSQL_FORMAT, strtotime("+".$alertDaysLimit." days"));
		} else {
			$alertDate = TODAY_ISO;
		}

		///////////////////////////////////////////////////////////////////////////////////////////////////
		///////////////////////////////////////////////////////////////////////////////////////////////////
		// GET LIST OF INVOICES ///////////////////////////////////////////////////////////////////////////
		///////////////////////////////////////////////////////////////////////////////////////////////////
		///////////////////////////////////////////////////////////////////////////////////////////////////

		$listObj = new \App\EntityList\Invoices();
		$listObj->setColumns(['invoiceNumber', 'invoiceDate', 'dueDate', 'idCorporate', 'printTotal'=>'total', 'currency', 'cashedStatus', 'cashedTotal', 'idUser']);
		$listObj->applyUserRestriction(false);
		$listObj->setFilter('invoiceDate', 'BETWEEN', [$this->invoiceStartDate, $this->invoiceEndDate]);
		$listObj->setFilter('dueDate', '<=', $alertDate);
		$listObj->setFilter('idCorporate', '>', '0');
		$listObj->setFilter('issueTime', '>', '0');
		$listObj->setFilter('voidTime', '=', '0');
		$listObj->setFilter('cashedStatus', 'IN', ['n','p']);

		$invoicesList = $listObj->exportRecords();

		///////////////////////////////////////////////////////////////////////////////////////////////////
		// LOOP THROUGH EACH INVOICE AND CHECK ITS DUE DATE ///////////////////////////////////////////////
		///////////////////////////////////////////////////////////////////////////////////////////////////

		// the alert date - if reached


		$invoicesStatus = ['dueDateDue'=>[], 'dueDatePanic'=>[], 'dueDateAlert'=>[]];

		if ($invoicesList) {
			foreach($invoicesList as $thisInvoice) {

				// saves the invoice id and then delete it from list
				$idCorporate = $thisInvoice['idCorporate'];
				unset($thisInvoice['id']);unset($thisInvoice['idCorporate']);

				// if invoice is in 'due' mode
				if ($thisInvoice['dueDate']<TODAY_ISO) {
					$invoicesStatus['dueDateDue'][$idCorporate]['totalDue'][$thisInvoice['currency']] += $thisInvoice['total'] - $thisInvoice['cashedTotal'];
					$invoicesStatus['dueDateDue'][$idCorporate]['totalInvoices'] += 1;
					continue;
				}

				// if invoice is in 'panic' zone
				if ($thisInvoice['dueDate']==TODAY_ISO) {
					$invoicesStatus['dueDatePanic'][$idCorporate]['totalDue'][$thisInvoice['currency']] += $thisInvoice['total'] - $thisInvoice['cashedTotal'];
					$invoicesStatus['dueDatePanic'][$idCorporate]['totalInvoices'] += 1;
					continue;
				}

				// if invoice if in 'alert' zone
				if ($alertDaysLimit>0 and $thisInvoice['dueDate']<=$alertDate) {
					$invoicesStatus['dueDateAlert'][$idCorporate]['totalDue'][$thisInvoice['currency']] += $thisInvoice['total'] - $thisInvoice['cashedTotal'];
					$invoicesStatus['dueDateAlert'][$idCorporate]['totalInvoices'] += 1;
					continue;
				}
			}
		} else {
			$this->logger->idle("No invoice due date alerts have been found.");
		}
		unset($invoicesList);

		///////////////////////////////////////////////////////////////////////////////////////////////////
		// SEND EMAILS CONTAINING THE INVOICES LIST (BY CATEGORY) /////////////////////////////////////////
		///////////////////////////////////////////////////////////////////////////////////////////////////
		$emailsSent=0;
		foreach($invoicesStatus as $category=>$categoryDetails) {

			// if no invoices in this category
			if (!$categoryDetails) continue;

			// if no email set for this category - skip the sending of an email for this category
			if (!$this->settings[$category]) continue;

			// SEND EMAIL WITH THE WARNING ////////////////////////////////////////////////////////////////

			try {
				\DB::startTransaction();
				
				// GENERAL EMAIL DETAILS ----------------------------------------------------------------------
				$sender = \App\Config\AutoEmailSender::getInstance()->get('cronJobs');
				
				// Create email entity
				$mail = \Entity\Email::insert();
				$mail->fromEmail = $sender['email'];
				$mail->fromName = $sender['name'];

				// Get recipient emails
				$emails = [];
				// explode by "," or ";"
				$tempEmails = explode(",", $this->settings[$category]);
				foreach($tempEmails as $emailTmp){
					$emailsArr = explode(";",$emailTmp);
					foreach($emailsArr as $email){
						$emails[]=trim($email);
					}
				}
				$mail->to = $emails;

				// ADD SUBJECT --------------------------------------------------------------------------------
				if ($category == "dueDateDue") {
					$mail->subject = $_LANG['Admin']['CronJobs']['Management']['CorporateDueDateAlerts']['invoicesSendEmail']['subjectDueDateDue'];
				}
				elseif ($category == "dueDatePanic") {
					$mail->subject = $_LANG['Admin']['CronJobs']['Management']['CorporateDueDateAlerts']['invoicesSendEmail']['subjectDueDatePanic'];
				}
				elseif ($category == "dueDateAlert") {
					$mail->subject = sprintf($_LANG['Admin']['CronJobs']['Management']['CorporateDueDateAlerts']['invoicesSendEmail']['subjectDueDateAlert'], $alertDaysLimit);
				}

				// ADD BODY -----------------------------------------------------------------------------------

				// start body
				if ($category == "dueDateDue") {
					$message = $_LANG['Admin']['CronJobs']['Management']['CorporateDueDateAlerts']['invoicesSendEmail']['messageDueDateDue'];
				}
				elseif ($category == "dueDatePanic") {
					$message = $_LANG['Admin']['CronJobs']['Management']['CorporateDueDateAlerts']['invoicesSendEmail']['messageDueDatePanic'];
				}
				elseif ($category == "dueDateAlert") {
					$message = sprintf($_LANG['Admin']['CronJobs']['Management']['CorporateDueDateAlerts']['invoicesSendEmail']['messageDueDateAlert'], $alertDaysLimit);
				}

				// LIST INVOICES ------------------------------------------------------------------------------
				foreach($categoryDetails as $idCorporate=>$dueDetails) {

					// add corporate name
					$corpEnt = \Entity\Corporate::select($idCorporate);

					$appUrl = \Engine\Cache\General::getInstance('disk')->get('APP_URL');

					$corporateName = $appUrl ? "<a href='".$appUrl."disp.php?idEntity=".$idCorporate."&module=Partners%2FCorporates%2FDashboard&action=index'>". $corpEnt->alias."</a>" :  $corpEnt->alias;
					$message.="
				<div>
					<b>".$corpEnt->typeName." `".$corporateName."`: ";

					$arrayCount = count($dueDetails['totalDue']);
					foreach ($dueDetails['totalDue'] as $currency => $totalValue) {
						$arrayCount--;
						$message.= \App\Utils\PriceFormat::format($totalValue, $currency);
						if ($arrayCount) {
							$message.= " + ";
						}
					}

					$message.="</b>
					[<i>".$dueDetails['totalInvoices']." invoice(s)</i>]
				</div>

			";
				}

				// end body
				$message .= $_LANG['Admin']['CronJobs']['Management']['CorporateDueDateAlerts']['invoicesSendEmail']['messageEnd'];
				
				// Set body content
				$mail->body = $message;
				
				// Set email properties
				$mail->priority = 2; // normal priority
				$mail->category = 'CorporateDueDateAlerts';

				// Save email to queue - cron will handle sending
				$mail->save();
				
				\DB::commitTransaction();

				$emailsSent++;
			}
			catch (\App\Entity\Exception $e){
				\DB::rollbackTransaction();
				$this->logger->error(sprintf($_LANG['Admin']['CronJobs']['Management']['CorporateDueDateAlerts']['invoicesSendEmail']['emailError'], $e->getMessage()));
			}
		}

		$this->logger->success(sprintf($_LANG['Admin']['CronJobs']['Management']['CorporateDueDateAlerts']['invoicesSendEmail']['emailsSentSuccessfully'], $emailsSent));
	}

}
