<?php
namespace App\Cron\Job;

/**
 * The class will search for old fiscal and non-fiscal documents and delete them (only the actual files on the disk)
 * @author Dan
 */
class DeleteOldDocuments extends \App\Cron\Job\Utils\ShortRunningCronJobAbstract
{
	/**
	 * Cronjob category: {system|operational|financial|reporting}
	 * @var string
	 */
	protected $category = 'operational';


	/**
	 * Minimum delete periods accepted
	 * @var integer
	 */
	protected $fiscalDocsMinYears    = 10;
	protected $nonFiscalDocsMinYears = 2;


	/**
	 * {@inheritDoc}
	 * @see \App\Cron\Job\Utils\GeneralAbstract::getSettingsDialog()
	 */
	public function getSettingsDialog(array $fields)
	{
		$form = parent::getSettingsDialog($fields);

		$_LANG =  \App\Loader_Lang::getInstance()->getGlobal();
		$lang = \App\Loader_Lang::getInstance()->getSection("Admin/CronJobs/Management/DeleteOldDocuments");

		$formContainer = \Engine\Form\Container\Fieldset::create($_LANG['Admin']['CronJobs']['Management']['formFields']['legend']);
		$form->addContainer($formContainer);


		// CONFIGURE DELETE PERIODS
		$cont = \Engine\Form\Container\Fieldset::create($lang['options']['configureDocsPeriod']);
		$formContainer->addContainer($cont);

		$field = new \Engine\Form\Input\Select($lang['forms']['fiscalDocsYears'], 'fiscalDocsYears', $fields['settings']['fiscalDocsYears']);
		$field->setPossibleValues([
				'10' => '10',
				'11' => '11',
				'12' => '12',
				'13' => '13',
				'14' => '14',
				'15' => '15',
				'16' => '16',
				'17' => '17',
				'18' => '18',
				'19' => '19',
				'20' => '20',
		]);
		$field->showDefaultOption();
		$field->setStyle('width', '50');
		$field->setCustomHTML($_LANG['timeUnitName']['years']);
		$field->setTooltip($lang['tooltips']['fiscalDocsYears']);
		$cont->addElement($field);

		$field = new \Engine\Form\Input\Select($lang['forms']['nonFiscalDocsYears'], 'nonFiscalDocsYears', $fields['settings']['nonFiscalDocsYears']);
		$field->setPossibleValues([
				'2' => '2',
				'3' => '3',
				'4' => '4',
				'5' => '5',
				'6' => '6',
				'7' => '7',
				'8' => '8',
				'9' => '9',
				'10' => '10',
		]);
		$field->showDefaultOption();
		$field->setStyle('width', '50');
		$field->setCustomHTML($_LANG['timeUnitName']['years']);
		$field->setTooltip($lang['tooltips']['nonFiscalDocsYears']);
		$cont->addElement($field);


		// CONFIGURE DOCUMENTS
		$cont = \Engine\Form\Container\Fieldset::create($lang['options']['configureFiscalDocs']);
		$formContainer->addContainer($cont);

		foreach (\App\Config\IssueDocuments::getInstance()->getDocsListByPivot() as $pivot=>$docsList) {
			$field = new \Engine\Form\Input\Checkboxes($_LANG['documentPivotName'][$pivot], 'fiscalDocuments['.$pivot.']', $fields['settings']['fiscalDocuments'][$pivot]);
			$field->setPossibleValues($docsList);
			$cont->addElement($field);
		}

		$cont = \Engine\Form\Container\Fieldset::create($lang['options']['configureNonFiscalDocs']);
		$formContainer->addContainer($cont);

		foreach (\App\Config\IssueDocuments::getInstance()->getDocsListByPivot() as $pivot=>$docsList) {
			$field = new \Engine\Form\Input\Checkboxes($_LANG['documentPivotName'][$pivot], 'nonFiscalDocuments['.$pivot.']', $fields['settings']['nonFiscalDocuments'][$pivot]);
			$field->setPossibleValues($docsList);
			$cont->addElement($field);
		}

		$formContainer->groupInputsInArray("settings");

		return $form;
	}

	/**
	 * {@inheritDoc}
	 * @see \App\Cron\Job\Utils\GeneralAbstract::validateSettings()
	 */
	public function validateSettings(\App\Entity\Messages $msgs, array $fields)
	{
		$_LANG = \App\Loader_Lang::getInstance()->getGlobal();
		$lang = \App\Loader_Lang::getInstance()->getSection("Admin/CronJobs/Management/DeleteOldDocuments");

		// check delete periods
		if ($fields['settings']['fiscalDocsYears'] && $fields['settings']['fiscalDocsYears']<$this->fiscalDocsMinYears) {
			$msgs->addWarningText(sprintf($lang['errors']['invalidFiscalSchedule'], $this->fiscalDocsMinYears));
		}
		if ($fields['settings']['nonFiscalDocsYears'] && $fields['settings']['nonFiscalDocsYears']<$this->nonFiscalDocsMinYears) {
			$msgs->addWarningText(sprintf($lang['errors']['invalidNonFiscalSchedule'], $this->nonFiscalDocsMinYears));
		}

		// check that documents do not overlap
		if ($fields['settings']['fiscalDocuments'] && $fields['settings']['nonFiscalDocuments']) {
			foreach ($fields['settings']['fiscalDocuments'] as $pivot=>$docs) {
				if (array_intersect($docs, (Array)$fields['settings']['nonFiscalDocuments'][$pivot])) {
					$msgs->addWarningText(sprintf("Fiscal and non-fiscal documents cannot overlap for pivot `%s`.", $_LANG['documentPivotName'][$pivot]));
				}
			}
		}

		// check that the frequency is once per day or less
		if ($fields['scheduleOptions']['type']!='scheduled') {
			$msgs->addWarningText($lang['errors']['invalidSchedule']);
		}
	}

	/**
	 * (non-PHPdoc)
	 * @see \App\Cron\Job\Utils\GeneralAbstract::executeJob()
	 */
	protected function executeJob()
	{
		// FORCE FULL ACCESS RIGHTS ///////////////////////////////////////////////////////////////
		\App\UserAccess\CurrentUserAccessFast::getInstance()->becomeSuperUser();


		// DELETE FISCAL DOCUMENTS
		if ($this->settings['fiscalDocsYears'] && $this->settings['fiscalDocuments']) {
			$maxDocDate = \Engine\DateTime::create("-{$this->settings['fiscalDocsYears']} years")->formatDateIso();

			$this->logger->info(sprintf("DELETING FISCAL DOCUMENS older than `%s` years (or `%s`).", $this->settings['fiscalDocsYears'], $maxDocDate));

			$this->deleteDocuments($this->settings['fiscalDocuments'], $maxDocDate);
		}
		else {
			$this->logger->info('Fiscal documents are not configured to be deleted.');
		}


		// DELETE NON-FISCAL DOCUMENTS
		if ($this->settings['nonFiscalDocsYears'] && $this->settings['nonFiscalDocuments']) {
			$maxDocDate = \Engine\DateTime::create("-{$this->settings['nonFiscalDocsYears']} years")->formatDateIso();

			$this->logger->info(sprintf("DELETING NON-FISCAL DOCUMENS older than `%s` years (or `%s`).", $this->settings['nonFiscalDocsYears'], $maxDocDate));

			$this->deleteDocuments($this->settings['nonFiscalDocuments'], $maxDocDate);
		}
		else {
			$this->logger->info('Non-fiscal documents are not configured to be deleted.');
		}


		\App\UserAccess\CurrentUserAccessFast::getInstance()->becomeNormalUser();
	}


	/**
	 * PERFORM THE ACTUAL SEARCHING AND DELETION
	 * @param array $documents
	 * @param string $maxDocDate
	 */
	protected function deleteDocuments(Array $documents, $maxDocDate)
	{
		$_LANG = \App\Loader_Lang::getInstance()->getGlobal();

		// search old documents
		foreach ($documents as $pivot=>$docs) {

			$successCount = 0;

			$listObj = new \App\EntityList\Documents();
			$listObj->setColumns(['pivot', 'idPivot', 'docType', 'docDate']);
			$listObj->setFilter('pivot', '=', $pivot);
			$listObj->setFilter('docType', 'IN', array_keys($docs));
			$listObj->setFilter('docDate', '<', $maxDocDate);
			$listObj->setFilter('docFile', '!=', '');
			$listObj->applyUserRestriction(false);
			$docsDb = $listObj->exportRecords();

			foreach ($docsDb as $docDb) {

				// delete file
				\DB::startTransaction();
				try {
					$docEnt = \Entity\Document::deleteFile($docDb['id']);
					$docEnt->save();
					\DB::commitTransaction();

					$successCount++;
				}
				catch (\App\Entity\Exception $ex) {
					\DB::rollbackTransaction();

					$this->logger->error(sprintf("Cannot delete document `%s` from `%s` (doc type: %s; pivot: %s; pivot Id: %s). Error: %s", $docDb['id'], $docDb['docDate'], $docDb['docType'], $_LANG['documentPivotName'][$docDb['pivot']], $docDb['idPivot'], $ex->getMessage()));
				}

			}

			if ($successCount) {
				$this->logger->success(sprintf("Deleted %s documents from the pivot: %s.", $successCount, $_LANG['documentPivotName'][$pivot]));
			}
		}
	}


}
