<?php

namespace App\AutoProcessRules;

class InvoiceCumulate_Definition extends DefinitionAbstract
{

	/**
	 * List with all available filters
	 * @var array
	 */
	protected $filtersConfig = [
		'invoiceDate',
		'invoiceResponsibleUser',
		'miceProjectType',
		'miceProject',
		'invoiceRemarks',
		'customers',
		'corporates',
		'corporateGroups',
		'invoiceContent',
	];

	/**
	 * List with filters for cache
	 * @var array
	 */
	protected $filtersCacheConfig = [
		'invoiceResponsibleUser' =>	'responsibleUser',
		'miceProject' =>			'miceProject',
		'invoiceRemarks' =>			'remarks',
		'customers' =>				'customer',
		'corporates' =>				'corporate',
	];

	/**
	 * List with all available fields
	 * @var array
	 */
	protected $fieldsConfig = [
		'processGrouping',
		'groupByInvoiceRemarkVar',
		'rowsGrouping',
		'idResponsibleUser',
		'idInvoiceSeries',
		'formOfPayment',
		'invoiceDueDays',
		'idAgencyBankAccount',
		'updateSingleInvoiceToNormalInvoice',
		'remarks'
	];

	/**
	 * List with fields for cached
	 * Value of array represents type of variable
	 * @var array
	 */
	protected $fieldsCacheConfig = [
		'processGrouping' =>		'processGrouping',
		'rowsGrouping' =>			'rowsGrouping',
		'idResponsibleUser' =>		'responsibleUser',
		'idInvoiceSeries' =>		'docSeries',
		'idAgencyBankAccount' =>	'agencyBankAccount',
	];

	/**
	 * (non-PHPdoc)
	 * @see \App\AutoProcessRules\DefinitionAbstract::checkFields()
	 */
	protected function checkFields(\App\MessagesCollector $msgs)
	{

		// check process grouping
		if ( !in_array($this->fields['processGrouping'], ['one', 'miceProject', 'invoiceRemark']) ) {
			$msgs->addWarning('Invalid/unset processing grouping field.');
		}

		// check service remark for grouping
		if ($this->fields['processGrouping']=='invoiceRemark' and strlen(!$this->fields['groupByInvoiceRemarkVar'])) {
			$msgs->addWarning('Invoice remark var must be set for this type of grouping.');
		}

		// check rows grouping
		if ( $this->fields['rowsGrouping'] and !in_array($this->fields['rowsGrouping'], ['vatPercentAndVatQuota', 'serviceType', 'serviceId', 'serviceIdAndRowType']) ) {
			$msgs->addWarning('Invalid rows grouping field.');
		}

		// check order responsible user
		if (!$this->fields['idResponsibleUser']) {
			$msgs->addWarning('No invoice responsible selected.');
		} else {
			$userEnt = \Entity\User::select($this->fields['idResponsibleUser']);
			if (!$userEnt->recordExists() or $userEnt->deleted) {
				$msgs->addWarning('Invalid invoice responsible user id.');
			}
		}

		// id invoice series
		if ($this->fields['idInvoiceSeries']) {
			$ser = \Entity\DocumentSeries::select($this->fields['idInvoiceSeries']);
			if (!$ser->recordExists() or $ser->deleted) {
				$msgs->addWarning('Invalid invoice series.');
			}
		}

		// check form of payment
		if ($this->fields['formOfPayment'] and !\App\Config\FormsOfPayment::getInstance()->check($this->fields['formOfPayment'])) {
			$msgs->addWarning('Invalid form of payment.');
		}

		// check the dueDays
		if ($this->fields['invoiceDueDays'] and (!is_numeric($this->fields['invoiceDueDays']) or $this->fields['invoiceDueDays']<0)) {
			$msgs->addWarning('The due days is not valid - it should be a positive integer.');
		}

		// check agency bank account
		if ($this->fields['idAgencyBankAccount']) {
			$abaEnt = \Entity\AgencyBankAccount::select($this->fields['idAgencyBankAccount']);
			if (!$abaEnt->recordExists() or $abaEnt->deleted) {
				$msgs->addWarning('Invalid agency bank account.');
			}
		}

		if ($this->fields['updateSingleInvoiceToNormalInvoice'] and !is_bool($this->fields['updateSingleInvoiceToNormalInvoice'])) {
			$msgs->addWarning('Transforming single invoices to normal invoices must be a boolean value.');
		}

	}


	/**
	 * (non-PHPdoc)
	 * @see \App\AutoProcessRules\DefinitionAbstract::checkFilters()
	 */
	protected function checkFilters(\App\MessagesCollector $msgs)
	{

		// check invoice date
		if ($this->filters['invoiceDate']) {
			if ( !($this->filters['invoiceDate'] instanceof \App\Utils\SmartDateInterval) ) {
				$msgs->addError('Invalid smart date interval for invoice date.');
			} else {
				$msgsTemp = new \App\MessagesCollector();
				$this->filters['invoiceDate']->check($msgsTemp);
				$msgs->appendMessages($msgsTemp, 'Invoice date problem: %s');
			}
		} else {
			$msgs->addWarning('No interval set for invoice date.');
		}

		// check users
		if ($this->filters['invoiceResponsibleUser']) {
			if (!is_array($this->filters['invoiceResponsibleUser']) ) {
				$msgs->addError('The invoice responsible users must be set as a list.');
			} else {
				foreach ($this->filters['invoiceResponsibleUser'] as $idUser) {
					$userEnt = \Entity\User::select($idUser);
					if (!$userEnt->recordExists() or $userEnt->deleted) {
						$msgs->addError(sprintf('Invalid responsible user id - %s.', $idUser));
					}
				}
				// check for duplicated users
				if (count($this->filters['invoiceResponsibleUser'])!=count(array_unique($this->filters['invoiceResponsibleUser']))) {
					$msgs->addWarning('Found some duplicated users in the list.');
				}
			}
		}

		// check MICE type
		if ($this->filters['miceProjectType']) {
			switch ($this->filters['miceProjectType']) {
				case 'all': case 'none': {
					break;
				}
				case 'custom': {
					if (!$this->filters['miceProject']) {
						$msgs->addWarning('You must select at least one MICE project.');
					}
					break;
				}
				default : {
					$msgs->addError('Invalid MICE project type.');
				}
			}
		}

		// check MICE projects
		if ($this->filters['miceProject']) {
			if (!is_array($this->filters['miceProject'])) {
				$msgs->addError('The MICE projects must be set as array.');
			} else {
				foreach ($this->filters['miceProject'] as $idMiceProject) {
					$miceProjectEnt = \Entity\MiceProject::select($idMiceProject);
					if (!$miceProjectEnt->recordExists()) {
						$msgs->addError("Found an invalid id for a MICE project.");
					}
					elseif ($miceProjectEnt->deleted) {
						$msgs->addWarning("A MICE project has been deleted in the meantime and it cannot be selected.");
					}
					elseif ($miceProjectEnt->closed) {
						$msgs->addWarning("A MICE project has been closed in the meantime and it cannot be selected.");
					}
				}
				// check for duplicated projects
				if (count($this->filters['miceProject'])!=count(array_unique($this->filters['miceProject']))) {
					$msgs->addWarning('Found some duplicated MICE projects in the list.');
				}
			}
		}

		// check invoice remark(s)
		if ($this->filters['invoiceRemarks']) {
			if (!is_array($this->filters['invoiceRemarks'])) {
				$msgs->addError('The invoice remark(s) must be set as a list.');
			} else {
				foreach($this->filters['invoiceRemarks'] as $idx=>$rmDet) {
					if (!in_array($rmDet['op'], ['anyValue', 'noValue', 'equal', 'notEqual'])) {
						$msgs->addError(sprintf('The operation for the invoice remark #%s is not valid.', $idx+1));
					}
					if (!$rmDet['var']) {
						$msgs->addWarning(sprintf('The variable name for the invoice remark #%s is not set.', $idx+1));
					}
					if (isset($rmDet['val']) and !is_array($rmDet['val'])) {
						$msgs->addError(sprintf('The variable value for the invoice remark #%s is not valid.', $idx+1));
					}
					if ( ($rmDet['op']=='equal' or $rmDet['op']=='notEqual') and !$rmDet['val']) {
						$msgs->addWarning(sprintf('The variable value for the invoice remark #%s is not set.', $idx+1));
					}
				}
			}
		}

		// check invoice contents
		if ($this->filters['invoiceContent']) {
			if (!is_array($this->filters['invoiceContent'])) {
				$msgs->addError("The invoice content must be set as a list.");
			}
			else {
				foreach($this->filters['invoiceContent'] as $ic) {
					if (!in_array($ic, ['issue', 'reverse', 'refund'])) {
						$msgs->addError(sprintf("The invoice content code `%s` is invalid.", $ic));
					}
				}
			}

		}
	}


	/**
	 *
	 * {@inheritDoc}
	 * @see \App\AutoProcessRules\DefinitionAbstract::getDescriptionFilters()
	 */
	public function getDescriptionFilters()
	{

		$filters = $this->getFilters();
		$descrFilters = [];

		// FILTERS
		foreach ($this->filtersConfig as $filterName) {
			switch ($filterName) {
				case 'invoiceDate':
					if ($filters['invoiceDate'] ){
						if ($filters['invoiceDate']->getReadableDescription()) {
							$descrFilters[] = "invoice date - ".$filters['invoiceDate']->getReadableDescription();
						}
					}
				break;

				case 'invoiceResponsibleUser':
					if ($filters['invoiceResponsibleUser']) {
						$descrFilters[] = sprintf("invoice responsible user - %s", \Entity\User::select($filters['invoiceResponsibleUser'])->name);
					}
				break;

				case 'miceProjectType':
					if ($filters['miceProjectType']) {
						$descrFilters[] = sprintf("MICE project type - %s", $filters['miceProjectType']);
					}
				break;

				case 'miceProject':
					if ($filters['miceProject']) {
						$micePrjList = [];
						foreach ($filters['miceProject'] as $idMiceProject) {
							$micePrjList[] = \Entity\MiceProject::select($idMiceProject)->name;
						}
						$descrFilters[] = sprintf("MICE project - %s", implode(', ', $micePrjList));
					}
				break;

				case 'invoiceRemarks':
					if ($filters['invoiceRemarks']) {
						$remark = null;
						foreach ($filters['invoiceRemarks'] as $value) {
							if ($value['op'] == 'equal') {
								$remark = sprintf('%s is equal to %s', $value['var'], implode(', ', $value['val']));
							} elseif ($value['op'] == 'notEqual') {
								$remark = sprintf('%s is not equal to %s', $value['var'], implode(', ', $value['val']));
							} else {
								$remark = sprintf('%s %s', $value['var'], $value['op']);
							}
						}
						$descrFilters[] = sprintf("invoice remarks - %s", $remark);
					}
				break;

				default: {
					$this->populateDescriptionCommonFilters($descrFilters, $filterName);
				}

			}
		}

		return implode('; ',$descrFilters);

	}


	/**
	 *
	 * {@inheritDoc}
	 * @see \App\AutoProcessRules\DefinitionAbstract::getDescriptionFields()
	 */
	public function getDescriptionFields()
	{

		$fields = $this->getFields();
		$descrFields = [];

		// FIELDS
		foreach ($this->fieldsConfig as $fieldName) {
			switch ($fieldName) {
				case 'idResponsibleUser':
					if ($fields['idResponsibleUser']) {
						$descrFields[] = sprintf('responsible user - %s', \Entity\User::select($fields['idResponsibleUser'])->name);
					}
				break;

				case 'idInvoiceSeries':
					if ($fields['idInvoiceSeries']) {
						$descrFields[] = sprintf('invoice series - %s', \Entity\DocumentSeries::select($fields['idInvoiceSeries'])->code);
					}
				break;

				case 'formOfPayment':
					if ($fields['formOfPayment']) {
						$descrFields[] = sprintf('form of payment - %s', \App\Config\FormsOfPayment::getInstance()->get($fields['formOfPayment']));
					}
				break;

				case 'idAgencyBankAccount':
					if ($fields['idAgencyBankAccount']) {
						$descrFields[] = sprintf('agency bank account - %s', \Entity\AgencyBankAccount::select($fields['idAgencyBankAccount'])->account);
					}
				break;

				case 'remarks':
					if ($fields['remarks']) {
						$descrFields[] = sprintf('remarks - %s', str_replace("\r\n", ' ', $fields['remarks']));
					}
				break;

				case 'invoiceDueDays': case 'processGrouping':
					if ($fields[$fieldName]) {
						$descrFields[] = $fieldName.' - '.$fields[$fieldName];
					}
				break;

				case 'updateSingleInvoiceToNormalInvoice':
					$descrFields[] = 'updates single invoices to normal invoice';
				break;

			}
		}

		return implode('; ',$descrFields);

	}

}
