<?php
namespace Modules\Documents\ImportedDocuments;

class ManualImportDocument
{

	/**
	 * This method checks the access for insert and the external system
	 * @param array $fields
	 * @param string $externalSystemCode
	 * @throws \App\MessagesException
	 */
	protected function checkInsert($fields, $externalSystemCode)
	{

		$_LANG = \App\Loader_Lang::getInstance()->getAll();

		$msgs = new \App\MessagesCollector();

		// user access
		if (!\App\UserAccess\CurrentUserAccessFast::getInstance()->hasAccessToOption("Modules/Documents/ImportedDocuments-insertManual")) {
			$msgs->addWarning($_LANG['Documents']['ImportedDocuments']['insert']['msgs']['noAccess']);
		}

		// external system
		$idExtSystem = \Entity\ImportedDocumentsSystem::getSystemIdByCode($externalSystemCode);
		if ($idExtSystem) {
			$extSystemEnt = \Entity\ImportedDocumentsSystem::select($idExtSystem);

			if (!$extSystemEnt->active) {
				$msgs->addWarning($_LANG['Documents']['ImportedDocuments']['insert']['msgs']['systemInactive']);
			}
		}
		else {
			$msgs->addWarning($_LANG['Documents']['ImportedDocuments']['insert']['msgs']['noSystemDefined']);
		}

		if ($msgs->hasErrorOrWarning()) {
			throw new \App\MessagesException($msgs);
		}

		$this->checkFields($fields);

	}

	/**
	 * This method checks the fields of the document
	 * @param array $fields
	 * @throws \App\MessagesException
	 */
	protected function checkFields($fields)
	{
		$_LANG = \App\Loader_Lang::getInstance()->getAll();
		$CFG = \Engine\Loader_Cfg::getInstance()->getGlobal();

		$msgs = new \App\MessagesCollector();

		// the document category is mandatory
 		if (!$fields['docCategory']) {
 			$msgs->addWarning($_LANG['Documents']['ImportedDocuments']['insert']['msgs']['docCategoryMandatory']);
 		}

 		// if you select the document category, you must set also the document type
 		if (($fields['docCategory']=='cashing' and !$fields['docTypeCashing']) or ($fields['docCategory']=='payment' and !$fields['docTypePayment'])) {
 			$msgs->addWarning($_LANG['Documents']['ImportedDocuments']['insert']['msgs']['docTypeMandatory']);
 		}

 		// the document number is mandatory
 		if (!$fields['docNumber'] && $CFG['Documents']['ImportedDocuments']['fields']['docNumber']=='mandatory') {
 			$msgs->addWarning($_LANG['Documents']['ImportedDocuments']['insert']['msgs']['docNumberMandatory']);
 		}

 		// the document date is mandatory
 		if (!$fields['docDate']) {
 			$msgs->addWarning($_LANG['Documents']['ImportedDocuments']['insert']['msgs']['docDateMandatory']);
 		}

 		// you must set the value and the currency for the imported document
 		if (!$fields['value']['value'] or !$fields['value']['currency']) {
 			$msgs->addWarning($_LANG['Documents']['ImportedDocuments']['insert']['msgs']['valueMandatory']);
 		}

 		// it is mandatory to set corporate/customer for cashing and supplier for payment
 		if ($fields['docCategory'] == 'payment' and !$fields['supplier']['id']) {
 			$msgs->addWarning($_LANG['Documents']['ImportedDocuments']['insert']['msgs']['supplierMandatory']);
 		}

 		if ($fields['docCategory'] == 'cashing' and !$fields['clientType']) {
 			$msgs->addWarning($_LANG['Documents']['ImportedDocuments']['insert']['msgs']['clientTypeMandatory']);
 		}

 		if ($fields['docCategory'] == 'cashing' and $fields['clientType'] and !$fields['corporate']['id'] and !$fields['customer']['id']) {
 			$msgs->addWarning($_LANG['Documents']['ImportedDocuments']['insert']['msgs']['clientMandatory']);
 		}

 		// check if the agency bank account is mandatory
 		if (!$fields['idAgencyBankAccount'] && $CFG['Documents']['ImportedDocuments']['fields']['agencyBankAccount']=='mandatory') {
 			$msgs->addWarning($_LANG['Documents']['ImportedDocuments']['insert']['msgs']['agencyBankAccMandatory']);
 		}

		// the entity id is mandatory
 		if ($fields['entity'] and !$fields['entityIds']) {
 			$msgs->addWarning($_LANG['Documents']['ImportedDocuments']['insert']['msgs']['entityIdNotSet']);
 		}

 		if ($fields['entity'] and $fields['docCategory']=='cashing' and $fields['entity']=='supplierInvoice') {
 			$msgs->addWarning($_LANG['Documents']['ImportedDocuments']['insert']['msgs']['wrongEntityForCashing']);
 		}

 		if ($fields['entity'] and $fields['docCategory']=='payment' and in_array($fields['entity'], ['service', 'importedService', 'invoice'])) {
 			$msgs->addWarning($_LANG['Documents']['ImportedDocuments']['insert']['msgs']['wrongEntityForPayment']);
 		}

 		// validate bank account
 		if ($fields['idAgencyBankAccount'] && !\Entity\AgencyBankAccount::select($fields['idAgencyBankAccount'])->recordExists()) {
 			$msgs->addWarning($_LANG['Documents']['ImportedDocuments']['insert']['msgs']['invalidAgencyBankAccount']);
 		}

 		if ($msgs->hasErrorOrWarning()) {
 			throw new \App\MessagesException($msgs);
 		}

	}

	/**
	 * This method checks the access to update a document, the document and the fields of the document
	 * @param int $id
	 * @param array $fields
	 * @throws \App\MessagesException
	 */
	protected function checkUpdate($id, $fields)
	{
		$_LANG = \App\Loader_Lang::getInstance()->getAll();

		$msgs = new \App\MessagesCollector();

		// document id
		if (!$id) {
			$msgs->addWarning($_LANG['Documents']['ImportedDocuments']['update']['msgs']['noIdToUpdate']);
		}

		// access
		if (!\App\UserAccess\CurrentUserAccessFast::getInstance()->hasAccessToOption("Modules/Documents/ImportedDocuments-updateManual")) {
			$msgs->addWarning($_LANG['Documents']['ImportedDocuments']['update']['msgs']['noAccess']);
		}

		$impDocument = \Entity\ImportedDocument::select($id);

		if (!$impDocument->recordExists()) {
			$msgs->addWarning($_LANG['Documents']['ImportedDocuments']['update']['msgs']['docNotExist']);
		}

		if ($impDocument->systemStatus=='cancelled') {
			$msgs->addWarning($_LANG['Documents']['ImportedDocuments']['update']['msgs']['docCancelled']);
		}

		if ($impDocument->status!='new' && $impDocument->status!='partial') {
			$msgs->addWarning($_LANG['Documents']['ImportedDocuments']['update']['msgs']['docNotNew']);
		}

		if ($msgs->hasErrorOrWarning()) {
 			throw new \App\MessagesException($msgs);
 		}

		$this->checkFields($fields);

	}

	/**
	 * This method check the access for cancel and the document
	 * @param int $id
	 * @throws \App\MessagesException
	 */
	protected function checkCancel($id)
	{
		$_LANG = \App\Loader_Lang::getInstance()->getAll();

		$msgs = new \App\MessagesCollector();

		// document id
		if (!$id) {
			$msgs->addWarning($_LANG['Documents']['ImportedDocuments']['cancel']['msgs']['noId']);
		}

		// access
		if (!\App\UserAccess\CurrentUserAccessFast::getInstance()->hasAccessToOption("Modules/Documents/ImportedDocuments-cancelManual")) {
			$msgs->addWarning($_LANG['Documents']['ImportedDocuments']['cancel']['msgs']['noAccess']);
		}

		$impDocument = \Entity\ImportedDocument::select($id);

		if (!$impDocument->recordExists()) {
			$msgs->addWarning($_LANG['Documents']['ImportedDocuments']['cancel']['msgs']['docNotExist']);
		}

		if ($impDocument->systemStatus=='cancelled') {
			$msgs->addWarning($_LANG['Documents']['ImportedDocuments']['cancel']['msgs']['docCancelled']);
		}

		if ($impDocument->status!='new') {
			$msgs->addWarning($_LANG['Documents']['ImportedDocuments']['cancel']['msgs']['docNotNew']);
		}

		if ($msgs->hasErrorOrWarning()) {
 			throw new \App\MessagesException($msgs);
 		}

	}


	/**
	 *
	 * @param array $fields
	 * @param string $externalSystemCode
	 */
	protected function populateImportedDocumentObject($fields)
	{
		if ($fields['docCategory'] == 'cashing') {
			$impDocObj = new \App\ImportedDocument\Cashing();
			$impDocObj->docType = $fields['docTypeCashing'];

			if ($fields['clientType'] == 'legalEnt') {
				$corporateObj = new \App\ImportedDocument\Corporate();
				$corporateObj->idTina = $fields['corporate']['id'];

				if ($fields['corporateBankAccount']['id']) {
					$corporateBankAccountObj = new \App\ImportedDocument\CorporateBankAccount();
					$corporateBankAccountObj->idTina = $fields['corporateBankAccount']['id'];

					$corporateObj->setBankAccount($corporateBankAccountObj);
				}

				// create empty customer object because merger will validate if exists and will copy into new object
				$impDocObj->setCustomer(new \App\ImportedDocument\Customer());
				$impDocObj->setCorporate($corporateObj);

			}
			else {
				$customerObj = new \App\ImportedDocument\Customer();
				$customerObj->idTina = $fields['customer']['id'];

				// create empty corporate object because merger will validate if exists and will copy into new object
				$impDocObj->setCorporate(new \App\ImportedDocument\Corporate());
				$impDocObj->setCustomer($customerObj);
			}

			$impDocObj->clearInvoicesList();
			$impDocObj->clearTinaServicesList();
			$impDocObj->clearImportedServicesList();
		}
		else {
			$impDocObj = new \App\ImportedDocument\Payment();
			$impDocObj->docType = $fields['docTypePayment'];

			$supplierObj = new \App\ImportedDocument\Supplier();
			$supplierObj->idTina = $fields['supplier']['id'];

			if ($fields['supplierBankAccount']['id']) {
				$supplierBankAccountObj = new \App\ImportedDocument\SupplierBankAccount();
				$supplierBankAccountObj->idTina = $fields['supplierBankAccount']['id'];

				$supplierObj->setBankAccount($supplierBankAccountObj);
			}

			$impDocObj->setSupplier($supplierObj);

			$impDocObj->clearSupplierInvoicesList();
		}

		$impDocObj->docDate 			= $fields['docDate'];
		$impDocObj->docNumber 			= $fields['docNumber'];
		$impDocObj->value 				= $fields['value']['value'];
		$impDocObj->currency 			= $fields['value']['currency'];
		$impDocObj->comments 			= $fields['comments'];
		$impDocObj->explanations 		= $fields['explanations'];
		$impDocObj->remarks 		    = $fields['remarks'];

		// agency bank account
		if ($fields['idAgencyBankAccount']) {
			$agencyBankObj = new \App\ImportedDocument\AgencyBankAccount();
			$agencyBankObj->idTina = $fields['idAgencyBankAccount'];
			$impDocObj->setAgencyBankAccount($agencyBankObj);
		}
		else {
			$agencyBankObj = new \App\ImportedDocument\AgencyBankAccount();
			$impDocObj->setAgencyBankAccount($agencyBankObj);
		}

		$respUser = new \App\ImportedDocument\User();
		$respUser->idTina = CURRENT_ID_USER;
		$impDocObj->setResponsibleUser($respUser);

		$respOffice = new \App\ImportedDocument\Office();
		$respOffice->idTina = CURRENT_ID_OFFICE;
		$impDocObj->setResponsibleOffice($respOffice);

		if ($fields['entity']) {
			switch ($fields['entity']) {
				case 'service':
					foreach ($fields['entityIds'] as $entityId) {
						$serviceObj = new \App\ImportedDocument\Service();
						$serviceObj->idTina = $entityId;

						$impDocObj->addTinaService($serviceObj);
					}
				break;

				case 'importedService':
					foreach ($fields['entityIds'] as $entityId) {
						$serviceObj = new \App\ImportedDocument\ImportedService();
						$serviceObj->idTina = $entityId;

						$impDocObj->addImportedService($serviceObj);
					}
				break;

				case 'invoice':
					foreach ($fields['entityIds'] as $entityId) {
						$invoiceObj = new \App\ImportedDocument\ClientInvoice();
						$invoiceObj->idTina = $entityId;

						$impDocObj->addInvoice($invoiceObj);
					}
				break;

				case 'supplierInvoice':
					foreach ($fields['entityIds'] as $entityId) {
						$suppInvoiceObj = new \App\ImportedDocument\SupplierInvoice();
						$suppInvoiceObj->idTina = $entityId;

						$impDocObj->addSupplierInvoice($suppInvoiceObj);
					}
				break;

			}
		}

		return $impDocObj;

	}

	/**
	 * Insert a new imported document
	 * @param array $fields
	 * @param string $externalSystemCode
	 */
	public function insert($fields, $externalSystemCode)
	{

		// check
		$this->checkInsert($fields, $externalSystemCode);

		// populate the imported document object
		$impDocObj = $this->populateImportedDocumentObject($fields);

		$impDocObj->externalSystemCode = $externalSystemCode;
		$impDocObj->operation = 'add';
		$impDocObj->idDocumentSystem = sprintf('%s_%s_%s', $externalSystemCode, $fields['docCategory'], uniqid());

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

		return $importedDocumentEnt->getId();

	}


	/**
	 * Update an imported document
	 * @param int $id
	 * @param array $fields
	 */
	public function update($id, $fields)
	{

		// check
		$this->checkUpdate($id, $fields);

		// populate the imported document
		$impDocObj = $this->populateImportedDocumentObject($fields);

		$oldImpDocEnt = \Entity\ImportedDocument::selectForUpdate($id);

		$impDocObj->externalSystemCode = $oldImpDocEnt->externalSystem->code;
		$impDocObj->operation = 'update';
		$impDocObj->idDocumentSystem = $oldImpDocEnt->idSystem;

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

	}


	/**
	 * Cancel an imported document
	 * @param int $id
	 */
	public function cancel($id)
	{

		// check
		$this->checkCancel($id);

		// cancel the document
		$impDocEnt = \Entity\ImportedDocument::selectForUpdate($id);

		$impDocObj = $impDocEnt->object;
		$impDocObj->operation = 'cancel';

		$impDocEntUpd = \Entity\ImportedDocument::insert();
		$impDocEntUpd->document = $impDocObj;

		$impDocEntUpd->save();
	}
}