<?php
namespace Modules\Invoices\SupplierInvoices\ImportStatements\Suppliers\Expedia;

class Model extends \Modules\Invoices\SupplierInvoices\ImportStatements\Model\XlsxAbstract
{
	public $headers = [
		'REP1' => [
			'idAffiliate'			=>	'Affiliate Id',
			'transactionType'		=>	'Transaction Type',
			'invoiceDate'			=>	'Transaction Date',
			'checkInDate'			=>	'Use Date Begin ',
			'useDateEnd'			=>	'Use Date End',
			'duration'				=>	'Night Count',
			'paxCount'				=>	'Total Person Count',
			'invoiceNumber'			=>	'EAN Itinerary ID',
			'confirmationId'		=>	'Confirmation ID',
			'affiliateReferenceNo'	=>	'Affiliate Reference Number',
			'currency'				=>	'Currency Code',
			'priceValue'			=>	'Amount',
			'amountPayable'			=>	'Amount Payable',
			'supplierProductName'	=>	'Hotel Name',
			'hotelCity'				=>	'Hotel City',
			'locationCode'			=>	'Hotel Country',
			'passengerLastName'		=>	'Last Name',
			'passengerFirstName'	=>	'First Name',
			'partnerType'			=>	'Partner Type',
			'refundReason'			=>	'Refund Reason',
			'eacOracleRef'			=>	'EAC Oracle Ref.',
			'idBookingItem'			=>	'Booking Item ID',
			'additionalData1'		=>	'AdditionalData1',
			'additionalData2'		=>	'AdditionalData2',
		],

		'REP2' => [
			'idAffiliate'			=>	'Affiliate Id',
			'transactionType'		=>	'Transaction Type',
			'invoiceDate'			=>	'Transaction Date',
			'checkInDate'			=>	'Use Date Begin ',
			'useDateEnd'			=>	'Use Date End',
			'duration'				=>	'Night Count',
			'paxCount'				=>	'Total Person Count',
			'invoiceNumber'			=>	'EAN Itinerary ID',
			'confirmationId'		=>	'Confirmation ID',
			'affiliateReferenceNo'	=>	'Affiliate Reference Number',
			'currency'				=>	'Currency Code',
			'priceValue'			=>	'Amount',
			'amountPayable'			=>	'Amount Payable',
			'supplierProductName'	=>	'Hotel Name',
			'hotelCity'				=>	'Hotel City',
			'locationCode'			=>	'Hotel Country',
			'passengerLastName'		=>	'Last Name',
			'passengerFirstName'	=>	'First Name',
			'partnerType'			=>	'Partner Type',
			'refundReason'			=>	'Refund Reason',
			'eacOracleRef'			=>	'EAC Oracle Ref.',
			'idBookingItem'			=>	'Booking Item ID',
			'additionalData1'		=>	'Additional Data1',
			'additionalData2'		=>	'Additional Data2',
		],
	];

	/**
	 * The payemnt due date (from file header)
	 * @var \Engine\DateTime
	 */
	private $dueDate;

	/**
	 *
	 * {@inheritDoc}
	 * @see \Modules\Invoices\SupplierInvoices\ImportStatements\Model\GeneralAbstract::check()
	 */
	public function check():void
	{
		// check input data
		if (!$this->inputData['idSupplier']['id']) {
			throw new \Modules\Invoices\SupplierInvoices\ImportStatements\Model\Exception("Supplier not set.");
		}
		else {
			$suppObj = \Entity\Supplier::select($this->inputData['idSupplier']['id']);
			if (!$suppObj->recordExists()) {
				throw new \Modules\Invoices\SupplierInvoices\ImportStatements\Model\Exception("Supplier not valid.");
			}
		}

		if (!$this->inputData['serviceCode']) {
			throw new \Modules\Invoices\SupplierInvoices\ImportStatements\Model\Exception("Service code not set.");
		}
		else {
			if (!\App\Config\Services_Basic::getInstance()->checkService($this->inputData['serviceCode'])) {
				throw new \Modules\Invoices\SupplierInvoices\ImportStatements\Model\Exception("Service code not valid.");
			}

			if (!$this->inputData['vatQuota']) {
				throw new \Modules\Invoices\SupplierInvoices\ImportStatements\Model\Exception("VAT quota not set.");
			}
			else {
				$rowVatCfg = \App\Config\SupplierInvoice_Vats::getInstance()->getAll();
				if (!array_key_exists($this->inputData['vatQuota'], $rowVatCfg[$this->inputData['serviceCode']]['list'])) {
					throw new \Modules\Invoices\SupplierInvoices\ImportStatements\Model\Exception("VAT quota not valid.");
				}
			}
		}
	}


	/**
	 * {@inheritDoc}
	 * @see \Modules\Invoices\SupplierInvoices\ImportStatements\Model\XlsxAbstract::detectFormat()
	 */
	protected function detectFormat(Array $rawRows):?string
	{
		$header1 = reset(array_filter(array_slice($rawRows,12,1)));
		$header2 = reset(array_filter(array_slice($rawRows,43,1)));

		foreach ($this->headers as $key => $header) {
			if (array_values($header) == array_filter(array_values($header1))) {
				return $key;
			}
			if (array_values($header) == array_filter(array_values($header2))) {
				return $key;
			}
		}

		return null;
	}


	/**
	 * Check if format is supported and cleanup rows
	 * {@inheritDoc}
	 * @see \Modules\Invoices\SupplierInvoices\ImportStatements\Model\XlsxAbstract::getCleanedRows()
	 */
	protected function getCleanedRows(Array $rawRows):array
	{
		$cleanedRows = [];

		$foundHeader = false;
		foreach ($rawRows as $key => $row) {
			$row = array_slice($row, 0, 24);

			if ($row == array_values($this->headers[$this->detectedFormat])) {
				$foundHeader = true;
				continue;
			}

			if ($this->detectedFormat == "REP1") {
				if (!$this->dueDate and strpos((string)reset($row), "Payment Due Date") !== false) {
					$this->dueDate = \Engine\DateTime::createFromFormat('d-M-Y', $row[1])->formatDateIso();
				}

				if ($row[2] and $row[20] and $foundHeader) {
					$cleanedRows[] = $row;
				}
			}
			elseif ($this->detectedFormat == "REP2") {
				if (!$this->dueDate and $row[3] and strpos($row[3], "Payment Due Date") !== false) {
					$this->dueDate = \Engine\DateTime::createFromFormat('d-M-Y', explode(": ", $row[3])[1])->formatDateIso();
				}

				if ($row[2] and $row[20] and $foundHeader) {
					$cleanedRows[] = $row;
				}
			}
		}

		return $cleanedRows;
	}


	/**
	 * {@inheritDoc}
	 * @see \Modules\Invoices\SupplierInvoices\ImportStatements\Model\GeneralAbstract::getGroupedRows()
	 */
	protected function getGroupedRows(Array $processedRows):array
	{
		$groupedRows = [];
		foreach ($processedRows as $row) {
			$groupedRows[$row['invoiceNumber']][] = $row;
		}

		return $groupedRows;
	}


	/**
	 * {@inheritDoc}
	 * @see \Modules\Invoices\SupplierInvoices\ImportStatements\Model\GeneralAbstract::populateSupplierInvoices()
	 */
	protected function populateSupplierInvoices():array
	{
		$suppInvEntList = [];

		foreach ($this->invoicesData as $invoiceNo => $invRows) {

			// get supplier invoice rows vat cfgs
			$rowVatCfg = \App\Config\SupplierInvoice_Vats::getInstance()->getAll();

			$suppInvEnt = \Entity\SupplierInvoice::insert();

			$suppInvEnt->invoiceNumber = 	$invoiceNo;
			$suppInvEnt->dueDate = 			$this->dueDate;
			$suppInvEnt->idSupplier	= 		$this->inputData['idSupplier']['id'];
			$suppInvEnt->idUser	= 			CURRENT_ID_USER;
			$suppInvEnt->idOffice	= 		CURRENT_ID_OFFICE;

			$rows = [];

			foreach ($invRows as $invRow) {
				$suppInvEnt->invoiceDate = 	\Engine\DateTime::createFromFormat('d-M-Y', $invRow['invoiceDate'])->formatDateIso();
				$suppInvEnt->currency = 	$invRow['currency'];


				$row = \Entity\SupplierInvoiceRow::insert();
				$row->checkIn = \Engine\DateTime::createFromFormat('d-M-Y', $invRow['checkInDate'])->formatDateIso();
				$row->confirmationNumber = 	$invoiceNo;

				if ($invRow['passengerLastName'] and $invRow['passengerFirstName']) {
					$customerEntMatch = new \App\EntityMatch\Customer('intersect');
					$customerEntMatch->setName($invRow['passengerLastName'], $invRow['passengerFirstName']);
					$customerEntMatch->search();

					if ($customerEntMatch->getResultsCount()==1) {
						$passenger = $customerEntMatch->getFirstMatchDetails();
						$row->idPassenger = $passenger['id'];
					}
				}

				if ($invRow['locationCode']) {
					$matchCountry = new \App\EntityMatch\Country('intersect');
					$matchCountry->setCode3($invRow['locationCode']);
					$matchCountry->search();
					if ($matchCountry->getResultsCount()==1) {
						$row->countryCode = $matchCountry->getFirstMatchId();
					}
				}

				if ($invRow['supplierProductName']) {
					$matchSupplierProduct = new \App\EntityMatch\SupplierProduct('intersect');
					$matchSupplierProduct->setProductName($invRow['supplierProductName'], false);
					$matchSupplierProduct->search();
					$row->idSupplierProduct = $matchSupplierProduct->getFirstMatchId();
				}

				$row->quantity = 			1;
				$row->serviceCode = 		$this->inputData['serviceCode'];
				$row->rowType = 			'price';
				$row->vatText = 			$this->inputData['vatQuota'];

				$vatPercent = $rowVatCfg[$this->inputData['serviceCode']]['list'][$this->inputData['vatQuota']];

				$price = 0;
				if ($invRow['transactionType'] == 'Cancel') {
					$price = (float)str_replace(['(', ')', ',', ' '], '', $invRow['priceValue']);
					$price = -1 * $price;
				}
				elseif ($invRow['transactionType'] == 'Book') {
					$price = (float)str_replace([',', ' '], '', $invRow['priceValue']);
				}

				$val = \App\Config\CurrencyDecimals::roundPrice($price*100/(100 + $vatPercent), $invRow['currency']);
				$vat = \App\Config\CurrencyDecimals::roundPrice($price - $val, $invRow['currency']);

				$row->priceValue = $val;
				$row->vatValue = $vat;

				$rows[] = $row;
			}

			$suppInvEnt->rows = $rows;
			$suppInvEntList[]= $suppInvEnt;
		}

		return $suppInvEntList;
	}
}

