<?php

namespace App\Webhook;

class ApplyEntityOperations
{

	/**
	 * The entity name (from TINA Entity classes).
	 * @var string
	 */
	private $entity;

	/**
	 * The entity id.
	 * @var int
	 */
	private $id;

	/**
	 * The Entity operation (eg. insert, update, delete, etc)
	 * @var string
	 */
	private $operation;

	/**
	 * Internal list of webhook actions that should be sent from a single entity operation in TINA.
	 * @var array
	 */
	private $webhookActions = null;

	/**
	 * Attached main entity details.
	 * @param string $entity
	 * @param int $id
	 * @param string $operation
	 */
	public function __construct(string $entity, int $id, string $operation)
	{
		$this->entity = $entity;
		$this->id = $id;
		$this->operation = $operation;
	}

	/**
	 * Adds a new record to the internal list of webhook actions.
	 * @param string $entity
	 * @param int $id
	 * @param string $action
	 */
	private function addWebhookAction(string $entity, int $id, string $action)
	{
		$this->webhookActions[] = ['entity'=>$entity, 'id'=>$id, 'action'=>$action];
	}

	/**
	 * Determines and populated the list of internal webhook actions based on the entity operation from TINA.
	 */
	public function determineActions()
	{

		// don't execute twice
		if ($this->webhookActions!==null) {
			return ;
		}

		$this->webhookActions = [];

		switch ($this->entity) {

			// CORPORATE / CUSTOMER / SUPPLIER ----------------------------------------------------
			case 'Corporate': case 'Customer': case 'Supplier':
				$this->determineActions_partners();
			break;

			// SERVICE  ---------------------------------------------------------------------------
			case 'Service':
				$this->determineActions_service();
			break;

			// INVOICE ----------------------------------------------------------------------------
			case 'Invoice':
				$this->determineActions_invoice();
			break;

			// INVOICE CASHING --------------------------------------------------------------------
			case 'InvoiceCashing':
				$this->determineActions_invoiceCashing();
			break;

			// DOCUMENT ---------------------------------------------------------------------------
			case 'Document':
				$this->determineActions_document();
			break;

		}

		return $this->webhookActions;
	}

	/**
	 * Manages actions for corporates, customers and suppliers operations.
	 */
	private function determineActions_partners() : void
	{
		switch ($this->operation) {
			case 'insert':
				$this->addWebhookAction($this->entity, $this->id, 'insert');
			break;
			case 'update': case 'markDuplicate': case 'unmarkDuplicate':
				$this->addWebhookAction($this->entity, $this->id, 'update');
			break;
			case 'delete':
				$this->addWebhookAction($this->entity, $this->id, 'delete');
			break;
		}
	}

	/**
	 * Manages webhook actions for Service entity.
	 */
	private function determineActions_service() :void
	{
		switch ($this->operation) {
			case 'insert':
				$this->addWebhookAction($this->entity, $this->id, 'insert');
			break;
			case 'update':
				$this->addWebhookAction($this->entity, $this->id, 'update');
				$this->addWebhookAction($this->entity, $this->id, 'statusOp');
				$this->addWebhookAction($this->entity, $this->id, 'statusFin');
			break;
			case 'cancel':
				$this->addWebhookAction($this->entity, $this->id, 'update');
				$this->addWebhookAction($this->entity, $this->id, 'statusOp');
			break;
			case 'createPackage':
				$this->addWebhookAction($this->entity, $this->id, 'insert');
			break;
		}

	}

	/**
	 * Manages webhook actions for Invoice entity.
	 */
	private function determineActions_invoice() : void
	{
		switch ($this->operation) {
			case 'insert':
				$this->addWebhookAction('Invoice', $this->id, 'insert');
			break;
			case 'update': case 'updateIssued':
				$this->addWebhookAction('Invoice', $this->id, 'update');
			break;
			case 'reverse':
				// TODO: vezi fct noua - nu am cum :(
			break;
			case 'cancel':
				$this->addWebhookAction('Invoice', $this->id, 'cancel');
			break;
			case 'duplicate':
				// cancel current invoice
				$this->addWebhookAction('Invoice', $this->id, 'cancel');
				// and insert a new one
				$newInvoiceEnt = \Entity\Invoice::select($this->id);
				$this->addWebhookAction('Invoice', $newInvoiceEnt->duplicatedOnInvoiceId, 'insert');
			break;
			case 'cumulate':
				$this->addWebhookAction('Invoice', $this->id, 'insert');
			break;
		}

		// add all services included on the invoice (available for all invoice operations)
		$invEnt = \Entity\Invoice::select($this->id);
		$includedServices = []; //
		foreach ($invEnt->rowsList as $rowDet) {
			// skip included services
			if ($includedServices[$rowDet['idReservationService']]) {
				continue;
			}
			$this->addWebhookAction('Service', $rowDet['idReservationService'], 'statusFin');
			// include the service in the list
			$includedServices[$rowDet['idReservationService']] = true;
		}

	}

	/**
	 * Manages webhook actions for InvoiceCashing entity.
	 */
	private function determineActions_invoiceCashing() : void
	{
		switch ($this->operation) {
			case 'insert': case 'update': case 'cancel':
				$this->addWebhookAction($this->entity, $this->id, $this->operation);
				// update invoice cashed status
				$invCashEnt = \Entity\InvoiceCashing::select($this->id);
				$this->addWebhookAction('Invoice', $invCashEnt->idInvoice, 'cashedStatus');

			break;
			case 'block': case 'unblock':
				$this->addWebhookAction($this->entity, $this->id, 'blockStatus');
			break;
		}

		// add all services included on the invoice (available for all invoice operations)
		if (in_array($this->operation, ['insert', 'update', 'cancel'])) {
			$invCashEnt = \Entity\InvoiceCashing::select($this->id);
			$includedServices = []; //
			foreach ($invCashEnt->invoice->rowsList as $rowDet) {
				// skip included services
				if ($includedServices[$rowDet['idReservationService']]) {
					continue;
				}
				$this->addWebhookAction('Service', $rowDet['idReservationService'], 'cashedStatus');
				// include the service in the list
				$includedServices[$rowDet['idReservationService']] = true;
			}
		}

	}

	/**
	 * Manages webhook actions for Document insert (issue).
	 */
	private function determineActions_document() : void
	{
		switch ($this->operation) {
			case 'insert':
				$this->addWebhookAction('Document', $this->id, 'insert');
				// update invoice cashed status
				$docEnt = \Entity\Document::select($this->id);
				if (
					$docEnt->pivotCode=='invoice' and !$docEnt->preview and
					\App\Config\IssueDocuments::getInstance()->isMainDocOnPivot($docEnt->docType)
				) {
					$this->addWebhookAction('Invoice', $docEnt->idPivot, 'issue');
				}
				if (
					$docEnt->pivotCode=='cashing' and !$docEnt->preview and
					\App\Config\IssueDocuments::getInstance()->isMainDocOnPivot($docEnt->docType)
				) {
					$this->addWebhookAction('InvoiceCashing', $docEnt->idPivot, 'issue');
				}
			break;
		}
	}


	/**
	 * Gets all determined actions and injects them into the queue.
	 */
	public function addEntityActionsToQueue()
	{

		$this->determineActions();

		$webhookCfg = \App\Config\WebhookQueue::getInstance();

		foreach ($this->webhookActions as $whAct) {
			if ($webhookCfg->getAutoQueueEntityAction($whAct['entity'], $whAct['action'])) {
				\App\Webhook\QueueManager::getInstance()->insertEntityAction($whAct['entity'], $whAct['id'], $whAct['action']);
			}
		}

	}

}

