<?php

namespace App\AutoProcessRules;

class ImportedDocProcess_Execution extends ExecutionAbstract
{

	/**
	 * (non-PHPdoc)
	 * @see \App\AutoProcessRules\ExecutionAbstract::execute()
	 */
	public function execute(\App\AutoProcessRules\Logs\Rule $ruleLogs)
	{

		// get the $stopOnFirstError flag
		$ruleEnt = \Entity\AutoProcessRule::select($this->idRule);
		$ruleObj = $ruleEnt->object;
		$stopOnFirstError = $ruleEnt->stopOnFirstError;


		// get invoices list mode
		switch ($ruleObj->getField('invoiceSuggestionsMode')) {
			case 'documentInvoices':
				$invoicesListMode = 'importedDoc';
			break;
			case 'partnerInvoices':
				$invoicesListMode = 'partnerInvoices';
			break;
			case 'allInvoices':
				$invoicesListMode = 'all';
			break;
		}

		// the invoice issue status (blank for "all")
		$invoiceIssueStatus = $ruleObj->getField('invoiceIssueStatus');

		// MAIN LOOP - go through each invoice and issue it ///////////////////////////////////////
		foreach($this->recordsList as $idImportedDoc) {

			$idTransaction = uniqid();

			// PROCESS IMPORTED DOCUMENT //////////////////////////////////////////////////////////
			try {

				$ruleLogs->addLog( \App\AutoProcessRules\Logs\Log::create('info', sprintf('Start importing the document #%s.', $idImportedDoc))->setEntityDetails('ImportedDocument', $idImportedDoc)->setIdTransaction($idTransaction) );

				\DB::startTransaction();

				$importedDocEnt = \Entity\ImportedDocument::selectForUpdate($idImportedDoc);

				if ($importedDocEnt->idCorporate) {
					$idPartner = $importedDocEnt->idCorporate;
					$partnerType = 'corporate';
				} elseif ($importedDocEnt->idCustomer) {
					$idPartner = $importedDocEnt->idCustomer;
					$partnerType = 'customer';
				}  elseif ($importedDocEnt->idSupplier) {
					$idPartner = $importedDocEnt->idSupplier;
					$partnerType = 'supplier';
				}

				// filter invoice currency
				$invoiceCurrency = $ruleObj->getField('invoiceCurrency');
				if ($invoiceCurrency=='docCurrency') {
					$invoiceCurrency = $importedDocEnt->docCurrency;
				}

				$impDocModel = new \Modules\Documents\ImportedDocuments\ProcessDocument\Model\Model();
				$invoices = $impDocModel->getInvoicesList($idImportedDoc, $idPartner, $partnerType, $invoicesListMode, 500);
				$invoicesToPay = $invoices['invoicesListToPay'];

				// some invoices found
				if ($invoicesToPay) {
					foreach ($invoicesToPay as $idInvoice) {

						// reload imported document details
						$importedDocEnt = \Entity\ImportedDocument::selectForUpdate($idImportedDoc);

						// cashing documents
						if ($importedDocEnt->docCategory == 'cashing' and $impDocModel->invoiceCanBePayed('cashing', $idInvoice, $idImportedDoc)) {

							$ruleLogs->addLog( \App\AutoProcessRules\Logs\Log::create('info', sprintf("Start processing the cashing document on client invoice #%s.", $idInvoice))->setEntityDetails('Invoice', $idInvoice)->setIdTransaction($idTransaction) );

							// filter by invoice issue status
							if ($invoiceIssueStatus) {
								$invoiceEnt = \Entity\Invoice::selectForUpdate($idInvoice);
								if ( ($invoiceIssueStatus=='issued' and !$invoiceEnt->issueTime) or ($invoiceIssueStatus=='notIssued' and $invoiceEnt->issueTime) ) {
									$message = sprintf( "The invoice #%s is ignored as it is filtered based on its issue status.", $idInvoice );
									$ruleLogs->addLog( \App\AutoProcessRules\Logs\Log::create('info',  $message)->setIdTransaction($idTransaction) );
									continue;
								}
							}

							// filter by invoice currency
							if ($invoiceCurrency) {
								$invoiceEnt = \Entity\Invoice::selectForUpdate($idInvoice);
								if ( $invoiceEnt->currency!=$invoiceCurrency ) {
									$message = sprintf( "The invoice #%s is ignored as it is filtered based on its currency.", $idInvoice );
									$ruleLogs->addLog( \App\AutoProcessRules\Logs\Log::create('info',  $message)->setIdTransaction($idTransaction) );
									continue;
								}
							}

							$invoiceCashingEnt = \Entity\InvoiceCashing::insert();
							$impDocModel->populateInvoiceCashing($invoiceCashingEnt, $importedDocEnt, $idInvoice);
							$invoiceCashingEnt->idUser = $ruleObj->getField('idUser');
							$invoiceCashingEnt->idOffice = \Entity\User::select($ruleObj->getField('idUser'))->idOffice;
							$invoiceCashingEnt->remarks = trim($invoiceCashingEnt->getField('remarks')."\r\n".$ruleObj->getField('remarks'));
							$invoiceCashingEnt->save();
							$message = sprintf( "A cashing document with id = %s was successfully processed on invoice #%s. Used doc amount on this invoice: %s.", $invoiceCashingEnt->getId(), $idInvoice, $invoiceCashingEnt->getField('value').' '.$invoiceCashingEnt->getField('currency') );
							$ruleLogs->addLog( \App\AutoProcessRules\Logs\Log::create('success',  $message)->setEntityDetails('InvoiceCashing', $invoiceCashingEnt->getId())->setIdTransaction($idTransaction) );
						}

						// payment documents
						if ($importedDocEnt->docCategory == 'payment' and $impDocModel->invoiceCanBePayed('payment', $idInvoice, $idImportedDoc)) {

							$ruleLogs->addLog( \App\AutoProcessRules\Logs\Log::create('info', sprintf("Start processing the payment document on supplier invoice #%s.", $idInvoice))->setEntityDetails('SupplierInvoice', $idInvoice)->setIdTransaction($idTransaction) );

							// filter by invoice currency
							if ($invoiceCurrency) {
								$suppInvoiceEnt = \Entity\SupplierInvoice::selectForUpdate($idInvoice);
								if ( $suppInvoiceEnt->currency!=$invoiceCurrency ) {
									$message = sprintf( "The supplier invoice #%s is ignored as it is filtered based on its currency.", $idInvoice );
									$ruleLogs->addLog( \App\AutoProcessRules\Logs\Log::create('info',  $message)->setIdTransaction($idTransaction) );
									continue;
								}
							}

							$supplierInvoicePaymentEnt = \Entity\SupplierInvoicePayment::insert();
							$impDocModel->populateSupplierInvoicePayment($supplierInvoicePaymentEnt, $importedDocEnt, $idInvoice);
							$supplierInvoicePaymentEnt->idUser = $ruleObj->getField('idUser');
							$supplierInvoicePaymentEnt->idOffice = \Entity\User::select($ruleObj->getField('idUser'))->idOffice;
							$supplierInvoicePaymentEnt->remarks = trim($supplierInvoicePaymentEnt->getField('remarks')."\r\n".$ruleObj->getField('remarks'));
							$supplierInvoicePaymentEnt->save();
							$message = sprintf( "A payment document with id = %s was successfully processed on invoice #%s. Used doc amount on this invoice: %s.", $supplierInvoicePaymentEnt->getId(), $idInvoice, $supplierInvoicePaymentEnt->getField('value').' '.$supplierInvoicePaymentEnt->getField('currency') );
							$ruleLogs->addLog( \App\AutoProcessRules\Logs\Log::create('success',  $message)->setEntityDetails('SupplierInvoicePayment', $supplierInvoicePaymentEnt->getId())->setIdTransaction($idTransaction) );
						}

					}

				} else {
					$ruleLogs->addQuickLog('warning', "No invoices found to be cashed/paid with this document.", $idTransaction);
				}

				\DB::commitTransaction();

			} catch (\App\Entity\Exception $e) {

				\DB::rollbackTransaction();

				$ruleLogs->addFromMessagesCollector($e->getMessagesCollector(), $idTransaction);

				// if "stopOnFirstError" - we need to stop this whole process
				if ($stopOnFirstError) {
					$ruleLogs->addQuickLog('warning', 'The process is set to stop after the first encountered problem.');
					break;
				}
			}

		}

	}


}

