<?php

namespace Modules\Admin\ImportEntities\Model\Import;

class ImportedDocumentsInsert extends \Modules\Admin\ImportEntities\Model\ImportAbstract
{

	/**
	 * the fields that can be imported for this type of entity
	 * @var array
	 */
	protected $fields = ['docCategory', 'docType', 'docNumber', 'docDate', 'value',
		'currency', 'explanations', 'bankAccount', 'partnerType', 'partnerName', 'partnerId',
		'invoiceNumber', 'invoiceDate', 'invoiceIdTina', 'limitProcessingValue', 'idDocumentSystem'];

	/**
	 * This entity uses the date format
	 * @var Boolean
	 */
	protected $useDateFormat = TRUE;

	public function process()
	{
		$_LANG = \App\Loader_Lang::getInstance()->getGlobal();

		$messagesFromImport = new \App\MessagesCollector();

		// group multiple invoices for the same document
		$documents = [];
		foreach ($this->fileData as $row) {

			// check informations from file
			if (!$row['docCategory']){
				$messagesFromImport->addWarning(sprintf($_LANG['Admin']['ImportEntities']['index']['msgs']['importedDocuments']['noDocCategory'], "{$row['docNumber']}/{$row['docDate']}"));
				continue;
			}
			elseif (!in_array($row['docCategory'], ['payment', 'cashing'])) {
				$messagesFromImport->addWarning(sprintf($_LANG['Admin']['ImportEntities']['index']['msgs']['importedDocuments']['anotherDocCategory'], "{$row['docNumber']}/{$row['docDate']}"));
				continue;
			}

			if (!$row['docType']){
				$messagesFromImport->addWarning(sprintf($_LANG['Admin']['ImportEntities']['index']['msgs']['importedDocuments']['noDocumentType'], "{$row['docNumber']}/{$row['docDate']}"));
				continue;
			}

			if ($row['docCategory']=='cashing'){
				if (!in_array($row['partnerType'], ['customer', 'corporate'])) {
					$messagesFromImport->addWarning(sprintf($_LANG['Admin']['ImportEntities']['index']['msgs']['importedDocuments']['wrongClientType'], "{$row['docNumber']}/{$row['docDate']}"));
					continue;
				}
			}

			if ($row['docCategory']=='payment') {
				if ($row['partnerType']!='supplier') {
					$messagesFromImport->addWarning(sprintf($_LANG['Admin']['ImportEntities']['index']['msgs']['importedDocuments']['wrongClientType'], "{$row['docNumber']}/{$row['docDate']}"));
					continue;
				}
			}

			$dateObj = \Engine\DateTime::createFromFormat($this->dateFormat, $row['docDate']);
			if (!$dateObj->isValid() or $dateObj->isEmpty()) {
				$messagesFromImport->addWarning(sprintf($_LANG['Admin']['ImportEntities']['index']['msgs']['importedDocuments']['invalidDocDate'], "{$row['docNumber']}/{$row['docDate']}"));
				continue;
			}

			if (!\App\Config\Currencies::getInstance()->check($row['currency'])){
				$messagesFromImport->addWarning(sprintf($_LANG['Admin']['ImportEntities']['index']['msgs']['importedDocuments']['invalidCurrency'], "{$row['docNumber']}/{$row['docDate']}"));
				continue;
			}

			$docKey = "{$row['docCategory']}_{$row['docNumber']}_{$row['docDate']}";

			// first invoice on document
			if (!$documents[$docKey]) {
				$documents[$docKey] = $row;
				$documents[$docKey]['error'] = false;
				$documents[$docKey]['invoices'][] = [
					'invoiceNumber'			=> $row['invoiceNumber'],
					'invoiceDate'			=> $row['invoiceDate'],
					'invoiceIdTina'			=> $row['invoiceIdTina'],
					'limitProcessingValue'	=> $row['limitProcessingValue'],
				];

				unset($documents[$docKey]['invoiceNumber']);
				unset($documents[$docKey]['invoiceDate']);
				unset($documents[$docKey]['invoiceIdTina']);
				unset($documents[$docKey]['limitProcessingValue']);
			}
			// additional invoices on document
			else {
				$documents[$docKey]['invoices'][] = [
					'invoiceNumber'			=> $row['invoiceNumber'],
					'invoiceDate'			=> $row['invoiceDate'],
					'invoiceIdTina'			=> $row['invoiceIdTina'],
					'limitProcessingValue'	=> $row['limitProcessingValue'],
				];
			}

			// check value and currency
			if ($documents[$docKey]['value'] != $row['value'] || $documents[$docKey]['currency'] != $row['currency']) {
				$messagesFromImport->addWarning(sprintf($_LANG['Admin']['ImportEntities']['index']['msgs']['importedDocuments']['currencyValueNotMatch'], "{$row['docNumber']}/{$row['docDate']}"));
				$documents[$docKey]['error'] = true;
			}
			// check docType
			if ($documents[$docKey]['docType'] != $row['docType']) {
				$messagesFromImport->addWarning(sprintf($_LANG['Admin']['ImportEntities']['index']['msgs']['importedDocuments']['docTypeNotMatch'], "{$row['docNumber']}/{$row['docDate']}"));
				$documents[$docKey]['error'] = true;
			}

		}


		// import the documents
		foreach ($documents as $doc) {
			if ($doc['error']) {
				continue;
			}

			try {
				\DB::startTransaction();

				// NEW
				if ($doc['docCategory'] == 'cashing') {
					$impDocObj = new \App\ImportedDocument\Cashing();

					if ($doc['partnerType']=="corporate"){
						$corporateObj = new \App\ImportedDocument\Corporate();

						if ($doc['partnerId']) {
							$corporateObj->idTina = $doc['partnerId'];
						}

						if ($doc['partnerName']) {
							$corporateObj->name = $doc['partnerName'];
						}

						$impDocObj->setCorporate($corporateObj);
					}
					elseif ($doc['partnerType']=="customer"){
						$customerObj = new \App\ImportedDocument\Customer();
						if ($doc['partnerId']) {
							$customerObj->idTina = $doc['partnerId'];
						}

						if ($doc['partnerName']) {
							$name = explode(' ', $doc['partnerName'], 2);
							$customerObj->firstName = $name['1'];
							$customerObj->lastName = $name['0'];
						}

						$impDocObj->setCustomer($customerObj);
					}
				}
				else {
					$impDocObj = new \App\ImportedDocument\Payment();

					$supplierObj = new \App\ImportedDocument\Supplier();
					if ($doc['partnerId']) {
						$supplierObj->idTina = $doc['partnerId'];
					}

					if ($doc['partnerName']) {
						$supplierObj->name = $doc['partnerName'];
					}
					$impDocObj->setSupplier($supplierObj);
				}

				$impDocObj->docType 			= $doc['docType'];
				$impDocObj->docNumber 			= $doc['docNumber'];
				$impDocObj->docDate 			= \Engine\DateTime::createFromFormat($this->dateFormat, $doc['docDate'])->formatDateIso();
				$impDocObj->value 				= $doc['value'];
				$impDocObj->currency 			= $doc['currency'];
				$impDocObj->operation 			= 'add';
				$impDocObj->explanations 		= $doc['explanations'];
				$impDocObj->externalSystemCode 	= 'manual';
				$impDocObj->idDocumentSystem 	= $doc['idDocumentSystem']?:$doc['docCategory'].$doc['docNumber'].$doc['docDate'];

				if ($doc['bankAccount']) {
					$bankAccountObj = new \App\ImportedDocument\AgencyBankAccount();
					$bankAccountObj->number = $doc['bankAccount'];

					$impDocObj->setAgencyBankAccount($bankAccountObj);
				}

				foreach ($doc['invoices'] as $inv) {
					if ($inv['invoiceNumber'] or $inv['invoiceDate'] or $inv['invoiceIdTina']) {
						if ($doc['docCategory'] == 'cashing') {
							$invoiceObj = new \App\ImportedDocument\ClientInvoice();
							if ($inv['invoiceNumber']) {
								$invoiceObj->number = $inv['invoiceNumber'];
							}
							$invDateObj = \Engine\DateTime::createFromFormat($this->dateFormat, $inv['invoiceDate']);
							if ($invDateObj->isValid() and !$invDateObj->isEmpty()) {
								$invoiceObj->date = $invDateObj->formatDateIso();
							}
							if ($inv['invoiceIdTina']) {
								$invoiceObj->idTina = $inv['invoiceIdTina'];
							}
							if ($inv['limitProcessingValue']) {
								$invoiceObj->limitProcessingValue = $inv['limitProcessingValue'];
								$invoiceObj->currency = $doc['currency'];
							}
							$impDocObj->addInvoice($invoiceObj);
						}
						else {
							$invoiceObj = new \App\ImportedDocument\SupplierInvoice();
							if ($inv['invoiceNumber']) {
								$invoiceObj->number = $inv['invoiceNumber'];
							}
							$invDateObj = \Engine\DateTime::createFromFormat($this->dateFormat, $inv['invoiceDate']);
							if ($invDateObj->isValid() and !$invDateObj->isEmpty()) {
								$invoiceObj->date = $invDateObj->formatDateIso();
							}
							if ($inv['invoiceIdTina']) {
								$invoiceObj->idTina = $inv['invoiceIdTina'];
							}
							if ($inv['limitProcessingValue']) {
								$invoiceObj->limitProcessingValue = $inv['limitProcessingValue'];
								$invoiceObj->currency = $doc['currency'];
							}
							$impDocObj->addSupplierInvoice($invoiceObj);
						}
					}

				}

				$importedDocumentEnt = \Entity\ImportedDocument::insert();
				$importedDocumentEnt->document = $impDocObj;
				$importedDocumentEnt->save();
				\DB::commitTransaction();

				$messagesFromImport->addSuccess(sprintf($_LANG['Admin']['ImportEntities']['index']['msgs']['importedDocuments']['ok'], "{$doc['docNumber']}/{$doc['docDate']}"));

			} catch (\App\Entity\Exception $e) {
				\DB::rollbackTransaction();
				$messagesFromImport->addWarning(sprintf($_LANG['Admin']['ImportEntities']['index']['msgs']['importedDocuments']['error'], $doc['docNumber'], $doc['docDate']));
				$messagesFromImport->appendMessages($e->getMessagesCollector());
			} catch (\App\MessagesException $e) {
				\DB::rollbackTransaction();
				$messagesFromImport->addWarning(sprintf($_LANG['Admin']['ImportEntities']['index']['msgs']['importedDocuments']['error'], $doc['docNumber'], $doc['docDate']));
				$messagesFromImport->appendMessages($e->getMessagesCollector());
			}

		}

		return $messagesFromImport;
	}

}