<?php
namespace Modules\Invoices\SupplierInvoices;

class Model extends \App\Mvc\Model_ListingAbstract
{

	/**
	 * (non-PHPdoc)
	 * @see \App\Mvc\Model_ListingAbstract::list_execute()
	 */
	public function list_execute(\App\Mvc\View\Listing\Members\Params $listingParams)
	{
		$filters = $listingParams->getFilters();

		// get the invoices list
		$listObj = new \App\EntityList\SupplierInvoices();
		$listObj->setColumns(['idSupplier', 'invoiceNumber', 'invoiceDate', 'addTime', 'totalValue',
			'currency', 'dueDate', 'idUser', 'idOffice', 'statusOp', 'statusFin', 'invoiceSeries', 'row.idBalance', 'payedValue',
			'idBlockUser', 'blockTime'
		]);
		$listObj->applyUserRestriction(true);

		// invoice date
		if ($filters['invoiceDate']['start']) {
			$listObj->setFilter('invoiceDate' , '>=', $filters['invoiceDate']['start']);
		}
		if ($filters['invoiceDate']['end']) {
			$listObj->setFilter('invoiceDate', "<=", $filters['invoiceDate']['end']);
		}

		// invoice status
		if ($filters['invoiceStatus']) {
			list($statusOp, $statusFin)=explode('|', $filters['invoiceStatus']);
			if ($statusOp && $statusFin) {
				$listObj->setCustomFilter('statusOp = ? AND statusFin = ?', [$statusOp, $statusFin]);
			} elseif ($statusOp) {
				$listObj->setFilter('statusOp', '=', $statusOp);
			}
		}

		// id
		if ($filters['id']) {
			$listObj->setFilter('inv.id', '=', $filters['id']);
		}

		// supplier
		// if supplier id belongs to a duplicated supplier, will look for that particular supplier
		// else if supplier id is main for one/more duplicates, will look for that supplier and all the duplicates it finds.
		if ($filters['supplier']['id']) {
			// we apply the filter
			$listObj->setFilter('inv.idSupplier', 'IN', \Entity\Supplier::select($filters['supplier']['id'])->fullDuplicatedSuppliersGroup);
		}

		// supplier product
		if ($filters['idSuppProduct']['id']) {
			$listObj->setFilter('row.idSupplierProduct', '=', $filters['idSuppProduct']['id']);
		}

		// service
		if ($filters['service']) {
			$listObj->setFilter('row.serviceCode', '=', $filters['service']);
		}

		if ($filters['currency']) {
			$listObj->setFilter('currency', '=', $filters['currency']);
		}

		// text filter
		if ($filters['textFilter']) {
			$listObj->setCustomFilter('invoiceComments LIKE ? OR invoiceSeries LIKE ? OR row.externalReservationId LIKE ? OR row.description LIKE ? OR row.contractNumber LIKE ?',
				["%{$filters['textFilter']}%", "%{$filters['textFilter']}%", "%{$filters['textFilter']}%", "%{$filters['textFilter']}%", "%{$filters['textFilter']}%"]);
		}

		// reservation id
		if ($filters['idReservation']) {
			if ($filters['idReservationType'] == "id") {
				// when you search by order id it will also search by order number
				$orderId = (int)\App\Utils\Db\TablesUtils::getInstance()->switchIdReservationConversion($filters['idReservation'], "normal");
				$orderNumber = \Entity\Order::select($orderId)->reservationNumber;

				$listObj->setCustomFilter('row.reservationId = ? OR row.reservationNumber = ? ', [$orderId, $orderNumber]);
			}
			if ($filters['idReservationType']=="code"){
				$listObj->setFilter('row.reservationCode', '=', $filters['idReservation']);
			}
			if ($filters['idReservationType']=="number"){
				$listObj->setFilter('row.reservationNumber', '=', $filters['idReservation']);
			}
			if ($filters['idReservationType']=='idService') {
				$servicesList = array_filter(array_map( function($a) {
					return trim($a);
				}, explode(",", $filters['idReservation'])));

				$searchByIdServiceSQL = "0";
				$bindingVars = [];
				foreach ($servicesList as $idService) {
					if (is_numeric($idService)) {
						$searchByIdServiceSQL.= " OR row.idService = ?";
						$bindingVars[] = $idService;
					}
					else {
						$searchByIdServiceSQL.= " OR row.idInvoice = ?";
						$bindingVars[] = false;
					}
				}

				$listObj->setCustomFilter($searchByIdServiceSQL, $bindingVars);
			}
		}

		// blocked invoices
		if ($filters['blockedInvoices'] == 'blocked') {
			$listObj->setFilter('blockTime', '!=', '0');
		}
		elseif ($filters['blockedInvoices'] == 'notBlocked') {
			$listObj->setFilter('blockTime', '=', '0');
		}

		// blockable invoices
		if ($filters['blockableInvoices'] == 'blockable') {
			$listObj->setFilter('blockable', '=', '1');
		}
		elseif ($filters['blockableInvoices'] == 'notBlockable') {
			$listObj->setFilter('blockable', '=', '0');
		}

		// due date
		if ($filters['dueDate']['start']) {
			$listObj->setFilter('dueDate', '>=', $filters['dueDate']['start']);
		}
		if ($filters['dueDate']['end']) {
			$listObj->setFilter('dueDate', "<=", $filters['dueDate']['end']);
		}

		// user
		if ($filters['user']) {
			list($idOffice, $idUser)=explode('|', $filters['user']['id']);
			if ($idUser) {
				$listObj->setFilter('idUser', '=', $idUser);
			} elseif ($idOffice) {
				$listObj->setFilter('idOffice', '=', $idOffice);
			}
		}

		// invoce number
		if ($filters['invoiceNumber']) {
			$listObj->setFilter('invoiceNumber', '=', $filters['invoiceNumber']);
		}

		// balanced rows
		if ($filters['balancedRows'] == 'balanced') {
			$listObj->setFilter('row.idBalance', '>', '0');
		}
		elseif ($filters['balancedRows'] == 'notBalanced') {
			$listObj->setFilter('row.idBalance', '=', '0');
		}

		// remarks
		if ($filters['remark']) {
			$listObj->setFilter('inv.processedRemarks', 'LIKE', "%{$filters['remark']}%");
		}

		if ($filters['idMiceProject']['id']) {
			$miceProject = \Entity\MiceProject::select($filters['idMiceProject']['id']);
			$listObj->setFilter('row.reservationId', 'IN', $miceProject->idOrders);
		}

		// form of payments
		if ($filters['formOfPayment']) {
			$listObj->setFilter('inv.formOfPayment', '=', $filters['formOfPayment']);
		}

		// total value
		if ($filters['totalValue']) {
			$listObj->setFilter('inv.totalValue', '=', $filters['totalValue']);
		}

		// ticket number
		if ($filters['ticketNumber']) {
			$listObj->setFilter('row.ticketNo', '=', $filters['ticketNumber']);
		}

		// groups filters
		if ($filters['idGroupElements']) {
			$idGroupElementsFilters = [];
			foreach($filters['idGroupElements'] as $groupCode=>$elementCode) {
				if ($elementCode) {
					$idGroupElementsFilters[$groupCode] = [$elementCode];
				}
			}
			// if at least one group selected
			if ($idGroupElementsFilters) {
				// gets the suppliers associated to the combination of these groups elements
				$supplierGroupsHelper = new \App\Utils\PartnerGroups\Supplier();
				$supplierGroupsHelper->setGroupElementsStructured($idGroupElementsFilters);
				$idAssociatedSuppliers = $supplierGroupsHelper->getPartnerIdsList();
				// filter by suppliers ids
				if ($idAssociatedSuppliers) {
					$listObj->setFilter('inv.idSupplier', 'IN', $idAssociatedSuppliers);
				} else { // if $idAssociatedSuppliers is empty, the list must be empty
					$listObj->setCustomFilter('0');
				}
			}
		}

		$listObj->setGroupBy('inv.id');
		$listObj = $this->entityList_inheritListingParams($listingParams, $listObj);
		$listObj->setOrderBy('id', $listingParams->getOrderDirection());

		// these must be called in this specific order
		$this->recordsList = $listObj->exportRecords();
		$this->totalRecordsCount = $listObj->getRecordsCount();
	}

	/**
	 * Get a list of suppliers related to a certain idGroupElement
	 *
	 * @param Int $idGroupElement
	 * @throws \DBException
	 * @return array
	 */
	protected function getSuppliersList($idGroupElement)
	{
		global $DBTSupplierGroups;

		$supplierGroupsList = \DB::getInstance()->getAll("SELECT * FROM `{$DBTSupplierGroups}` WHERE `idGroupElement`=? ORDER BY `idSupplier` DESC", [$idGroupElement]);
		if (\DB::getInstance()->ErrorNo()) {
			throw new \DBException("Cannot get related supplier list");
		}

		$supplierList = [];
		foreach ($supplierGroupsList as $supplierGroup) {
			$supplierList[] = $supplierGroup['idSupplier'];
		}

		return $supplierList;
	}
}
