<?php

namespace App\Config\ImportedDocuments;

class Matches extends \App\Config\DbMultiAssocVarsAbstract
{

	/**
	 * The primary key (the list of columns) for this table - in the correct order.
	 * @var array
	 */
	protected $dbTablePkCols= ['entityType', 'idEntityExtSys', 'idSystem'];

	/**
	 * The column that contains the actual value for this association.
	 * @var String
	 */
	protected $dbTableValueCol='idEntityTina';

	/**
	 * Indicates the table column name which stores the last update time for the current record;
	 * if nothing is set, the info is not saved in the db.
	 * @var String
	 */
	protected $dbTableLastUpdateTimeCol = 'lastUpdateTime';

	/**
	 * Indicates the table column name which stores the last update user id for the current record;
	 * if nothing is set, the info is not saved in the db.
	 * @var String
	 */
	protected $dbTableLastUpdateUserCol = 'idUpdateUser';

	/**
	 * (non-PHPdoc)
	 * @see \App\Config\DbMultiAssocVarsAbstract::getDbTableName()
	 */
	protected function getDbTableName()
	{
		global $DBTImportedDocuments_matches;
		return $DBTImportedDocuments_matches;
	}


	/**
	 * Sets a matching customer.
	 * @param Int $idSystem
	 * @param String $systemIdCustomer
	 * @param Int $tinaIdCustomer
	 */
	public function setCustomer($idSystem, $systemIdCustomer, $tinaIdCustomer)
	{
		$pkFields= [
			'entityType' =>		'customer',
			'idEntityExtSys' =>	$systemIdCustomer,
			'idSystem' =>		$idSystem,
		];
		return $this->set($pkFields, $tinaIdCustomer);
	}

	/**
	 * Sets a matching corporate.
	 * @param Int $idSystem
	 * @param String $systemIdCorporate
	 * @param Int $tinaIdCorporate
	 */
	public function setCorporate($idSystem, $systemIdCorporate, $tinaIdCorporate)
	{
		$pkFields= [
			'entityType' =>		'corporate',
			'idEntityExtSys' =>	$systemIdCorporate,
			'idSystem' =>		$idSystem,
		];
		return $this->set($pkFields, $tinaIdCorporate);
	}

	/**
	 * Sets a matching supplier.
	 * @param Int $idSystem
	 * @param String $systemIdSupplier
	 * @param Int $tinaIdSupplier
	 */
	public function setSupplier($idSystem, $systemIdSupplier, $tinaIdSupplier)
	{
		$pkFields= [
			'entityType' =>		'supplier',
			'idEntityExtSys' =>	$systemIdSupplier,
			'idSystem' =>		$idSystem,
		];
		return $this->set($pkFields, $tinaIdSupplier);
	}

	/**
	 * Sets a matching city.
	 * @param Int $idSystem
	 * @param String $systemIdSupplier
	 * @param Int $tinaIdSupplier
	 */
	public function setCity($idSystem, $systemIdCity, $tinaIdCity)
	{
		$pkFields= [
			'entityType' =>		'city',
			'idEntityExtSys' =>	$systemIdCity,
			'idSystem' =>		$idSystem,
		];
		return $this->set($pkFields, $tinaIdCity);
	}

	/**
	 * Sets a matching user.
	 * @param Int $idSystem
	 * @param String $systemIdSupplier
	 * @param Int $tinaIdSupplier
	 */
	public function setUser($idSystem, $systemIdSupplier, $tinaIdSupplier)
	{
		$pkFields= [
			'entityType' =>		'user',
			'idEntityExtSys' =>	$systemIdSupplier,
			'idSystem' =>		$idSystem,
		];
		return $this->set($pkFields, $tinaIdSupplier);
	}

	/**
	 * Sets a matching office.
	 * @param Int $idSystem
	 * @param String $systemIdSupplier
	 * @param Int $tinaIdSupplier
	 */
	public function setOffice($idSystem, $systemIdSupplier, $tinaIdSupplier)
	{
		$pkFields= [
			'entityType' =>		'office',
			'idEntityExtSys' =>	$systemIdSupplier,
			'idSystem' =>		$idSystem,
		];
		return $this->set($pkFields, $tinaIdSupplier);
	}

	public function setDocType($idSystem, $systemIdDocType, $tinaIdDocType)
	{
		$pkFields= [
			'entityType' =>		'docType',
			'idEntityExtSys' =>	$systemIdDocType,
			'idSystem' =>		$idSystem,
		];
		return $this->set($pkFields, $tinaIdDocType);
	}

	/**
	 * Sets a matching bank account.
	 * @param Int $idSystem
	 * @param String $systemIdSupplier
	 * @param Int $tinaIdSupplier
	 */
	public function setAgencyBankAccount($idSystem, $systemIdBankAccount, $tinaIdBankAccount)
	{
	    $pkFields=[
	        'entityType' =>		'agencyBankAccount',
	        'idEntityExtSys' =>	$systemIdBankAccount,
	        'idSystem' =>		$idSystem,
	    ];
	    return $this->set($pkFields, $tinaIdBankAccount);
	}

	/**
	 * (non-PHPdoc)
	 * @see \App\Config\BaseAbstract::save_check()
	 */
	protected function save_check()
	{

		// LOOP THROUGH EACH ITEM AND CHECK IT ////////////////////////////////////////////////////
		foreach($this->itemsList as $item) {

			// check the system id

			if ($item['value']===null) {
				continue;
			}

			// check by entity type
			switch ($item['pkFields']['entityType']) {

				// customer check
				case 'customer':
					if (!\Entity\Customer::select($item['value'])->recordExists() or \Entity\Customer::select($item['value'])->deleted) {
						$this->addErrorMessage(sprintf('Invalid customer id `%s`.', $item['value']));
					}
				break;

				// corporate check
				case 'corporate':
					if (!\Entity\Corporate::select($item['value'])->recordExists() or \Entity\Corporate::select($item['value'])->deleted) {
						$this->addErrorMessage(sprintf('Invalid corporate id `%s`.', $item['value']));
					}
				break;

				// supplier check
				case 'supplier':
					if (!\Entity\Supplier::select($item['value'])->recordExists() or \Entity\Supplier::select($item['value'])->deleted) {
						$this->addErrorMessage(sprintf('Invalid supplier id `%s`.', $item['value']));
					}
				break;

				// city check
				case 'city':
					if (!\Entity\City::select($item['value'])->recordExists() or \Entity\City::select($item['value'])->deleted) {
						$this->addErrorMessage(sprintf('Invalid city id `%s`.', $item['value']));
					}
				break;

				// user check
				case 'user':
					if (!\Entity\User::select($item['value'])->recordExists() or \Entity\User::select($item['value'])->deleted) {
						$this->addErrorMessage(sprintf('Invalid user id `%s`.', $item['value']));
					}
				break;

				// office check
				case 'office':
					if (!\Entity\Office::select($item['value'])->recordExists() or \Entity\Office::select($item['value'])->deleted) {
						$this->addErrorMessage(sprintf('Invalid office id `%s`.', $item['value']));
					}
				break;

				// document type
				case 'docType':

				break;

				// bank account check
				case 'agencyBankAccount':
				    if (!\Entity\AgencyBankAccount::select($item['value'])->recordExists() or \Entity\AgencyBankAccount::select($item['value'])->deleted) {
				        $this->addErrorMessage(sprintf('Invalid bank account id `%s`.', $item['value']));
				    }
				break;

				default: {
					$this->addErrorMessage(sprintf('Invalid entity type `%s`.', $item['pkFields']['entityType']));
				}
			}
		}
	}


	/**
	 * Gets the matched customer id.
	 * @param Int $idSystem
	 * @param String $systemIdCustomer
	 * @return Int
	 */
	public function getCustomer($idSystem, $systemIdCustomer)
	{
		return $this->searchAssoc(['entityType'=>'customer', 'idEntityExtSys'=>$systemIdCustomer, 'idSystem'=>$idSystem]);
	}

	/**
	 * Gets the matched corporate id.
	 * @param Int $idSystem
	 * @param String $systemIdCorporate
	 * @return Int
	 */
	public function getCorporate($idSystem, $systemIdCorporate)
	{
		return $this->searchAssoc(['entityType'=>'corporate', 'idEntityExtSys'=>$systemIdCorporate, 'idSystem'=>$idSystem]);
	}

	/**
	 * Gets the matched supplier id.
	 * @param Int $idSystem
	 * @param String $systemIdSupplier
	 * @return Int
	 */
	public function getSupplier($idSystem, $systemIdSupplier)
	{
		return $this->searchAssoc(['entityType'=>'supplier', 'idEntityExtSys'=>$systemIdSupplier, 'idSystem'=>$idSystem]);
	}

	/**
	 * Gets the matched city id.
	 * @param Int $idSystem
	 * @param String $systemIdCity
	 * @return Int
	 */
	public function getCity($idSystem, $systemIdCity)
	{
		return $this->searchAssoc(['entityType'=>'city', 'idEntityExtSys'=>$systemIdCity, 'idSystem'=>$idSystem]);
	}

	/**
	 * Gets the matched user id.
	 * @param Int $idSystem
	 * @param String $systemIdSupplier
	 * @return Int
	 */
	public function getUser($idSystem, $systemIdSupplier)
	{
		return $this->searchAssoc(['entityType'=>'user', 'idEntityExtSys'=>$systemIdSupplier, 'idSystem'=>$idSystem]);
	}

	/**
	 * Gets the matched office id.
	 * @param Int $idSystem
	 * @param String $systemIdSupplier
	 * @return Int
	 */
	public function getOffice($idSystem, $systemIdSupplier)
	{
		return $this->searchAssoc(['entityType'=>'office', 'idEntityExtSys'=>$systemIdSupplier, 'idSystem'=>$idSystem]);
	}

	/**
	 *
	 * @param Int $idSystem
	 * @param String $systemDocType
	 * @param String $docCategory
	 * @throws \DBException
	 */
	public function getDocType($idSystem, $systemDocType, $docCategory)
	{
		$searchSql = "SELECT * FROM $this->dbTableName
			WHERE
				`entityType` = 'docType' AND
				`idSystem` = ? AND
				`idEntityExtSys` = ?
		";

		$prepVals = [$idSystem, $systemDocType];

		$searchEx=\DB::getInstance()->Execute($searchSql, $prepVals);

		if (!$searchEx) {
			throw new \DBException('The search assoc failed for class '.get_called_class().' due to a technical problem.');
		}

		if (!$searchEx->RecordCount()) {
			$return = null;
		}
		// one record found
		else {
			$row=$searchEx->FetchRow();
			$return = str_replace($docCategory.":", '', $row['idEntityTina']);
		}

		return $return;

	}

	/**
	 * Gets the matched bank account.
	 * @param Int $idSystem
	 * @param String $systemIdCity
	 * @return Int
	 */
	public function getAgencyBankAccount($idSystem, $systemIdCity)
	{
	    return $this->searchAssoc(['entityType'=>'agencyBankAccount', 'idEntityExtSys'=>$systemIdCity, 'idSystem'=>$idSystem]);
	}

	/**
	 * Generalised function that replaces direct SQL calls
	 * @param Array $fields
	 * @throws \Exception
	 */
	protected function searchByFields($fields)
	{
		$values = 		[];
		$conditions = 	[];
		foreach($fields as $fld=>$val) {
			if(is_numeric($fld)) {
				// numeric array, or custom condition
				$conditions[] = $val;
			}
			else {
				$conditions[] = "`{$fld}`=?";
				$values[] = 	$val;
			}
		}

		$db = \DB::getInstance();

		// compose the sql
		$query = "SELECT * FROM `{$this->dbTableName}` WHERE ".implode(' AND ', $conditions);
		$queryResult = $db->Execute($query, $values);
		if ($db->ErrorNo()) {
			\Log::getInstance()->dbError("searchAssoc failed during SQL execution.");
			throw new \Exception('The search assoc failed for class '.get_called_class().' due to a technical problem.');
		}

		return $queryResult->GetAll();
	}

}