<?php

namespace Sibs\Sibs\Controller\Adminhtml\Payments;

use Magento\Backend\App\Action;
use Magento\Framework\Controller\ResultFactory;
use Sibs\Sibs\Model\SibsConstants;
use Sibs\Sibs\Model\SibsOrder;
use Sibs\Sibs\Utils\SibsException;
use Sibs\Sibs\Utils\SibsLog;
use Sibs\Sibs\Utils\SibsUtils;

class Orderstatus extends Action
{
    protected $_sibsOrder;

    protected $_messageManager;

    /**
     * @var \Sibs\Sibs\Helper\DataHelper
     */
    protected $_paymentHelper;

    /**
     * @var \Magento\Sales\Model\OrderRepository
     */
    protected $_orderRepository;

    public function __construct(
        \Magento\Backend\App\Action\Context $context,
        \Sibs\Sibs\Helper\DataHelper $paymentHelper,
        \Magento\Sales\Model\OrderRepository $orderRepository
    ) {
        parent::__construct($context);
        $this->_messageManager   = $context->getMessageManager();

        $this->_paymentHelper    = $paymentHelper;
        $this->_orderRepository  = $orderRepository;
    }

    public function execute()
    {
        SibsLog::info('Inquiry');

        $orderId          = $this->_request->getParam('order_id');
        $this->_sibsOrder = new SibsOrder($orderId);

        try {
            $transactionId = $this->getOrderLastTransctionId();
            $paymentMethod = $this->_sibsOrder->getPaymentMethodCode();
            $paymentType   = $this->getPaymentType();
            $token         = $this->_paymentHelper->getToken();
            $clientId      = $this->_paymentHelper->getClientID();

            SibsLog::info("INQUIRY - orderId: $orderId");
            SibsLog::info("INQUIRY - transactionId: $transactionId");
            SibsLog::info("INQUIRY - paymentMethod: $paymentMethod");
            SibsLog::info("INQUIRY - token: $token");
            SibsLog::info("INQUIRY - clientId: $clientId");

            $url = $this->_paymentHelper->getUrlStatus($transactionId);
            SibsLog::info("INQUIRY - url: $url");

            $responseArray = $this->_paymentHelper->get_payment_result($url, $token, $clientId);
            SibsLog::info('INQUIRY - Status Response: ' . SibsLog::prettify($responseArray));

            list($paymentStatus, $amountValue) = $this->getAndValidateResponse($responseArray);

            list($orderState, $orderStatus) = $this->_paymentHelper->sibs_get_order_state_and_status($paymentStatus, $paymentType);
            SibsLog::info("INQUIRY - Order state: $orderState");
            SibsLog::info("INQUIRY - Order status: $orderStatus");

            if (! in_array($paymentMethod, SibsConstants::SIBS_PAYMENTS)) {
                throw new SibsException(__('Error getting Order Status. Payment Method is not from SIBS.'));
            }

            $this->makeInquiry($orderState, $orderStatus, $paymentStatus, $amountValue, $paymentType);
        } catch(SibsException $e) {
            $this->_messageManager->addErrorMessage($e->getMessage());
        } finally {
            $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
            $resultRedirect->setPath('sales/order/view', ['order_id' => $orderId]);

            return $resultRedirect;
        }
    }

    private function getAndValidateResponse($response)
    {
        if (empty($response['returnStatus']['statusCode'])) {
            throw new SibsException('Missing [returnStatus][statusCode]');
        } elseif (SibsUtils::getTransactionResult($response['returnStatus']['statusCode']) == SibsConstants::SIBS_NOK) {
            throw new SibsException('Request NOK');
        }

        if (empty($response['paymentStatus'])) {
            throw new SibsException('Missing [paymentStatus]');
        }

        if (empty($response['amount']['value'])) {
            throw new SibsException('Missing [amount][value]');
        }

        return [
            $response['paymentStatus'], $response['amount']['value'],
        ];
    }

    private function getOrderLastTransctionId()
    {
        if ($this->_sibsOrder->isRefunded()) {
            $refundedId = $this->_sibsOrder->getRefundedId();
            SibsLog::info("INQUIRY - refundedId: $refundedId");

            return $refundedId;
        } elseif ($this->_sibsOrder->isCaptured()) {
            $captureId = $this->_sibsOrder->getCaptureId();
            SibsLog::info("INQUIRY - captureId: $captureId");

            return $captureId;
        } else {
            $referenceId = $this->_sibsOrder->getReferenceId();
            SibsLog::info("INQUIRY - referenceId: $referenceId");

            return $referenceId;
        }
    }

    private function getPaymentType()
    {
        if ($this->_sibsOrder->isRefunded()) {
            return SibsConstants::SIBS_PAYMENT_TYPE_RFND;
        } elseif ($this->_sibsOrder->isCaptured()) {
            return SibsConstants::SIBS_PAYMENT_TYPE_CAPT;
        } else {
            return $this->_sibsOrder->getPaymentType();
        }
    }

    private function makeInquiry($orderState, $orderStatus, $paymentStatus, $amountValue, $paymentType)
    {
        if ($this->_sibsOrder->isRefunded()) {
            $refundStatus = $this->_paymentHelper->sibs_get_capture_refund_status($paymentStatus);
            SibsLog::info("INQUIRY - Refund status: $refundStatus");
            $this->inquiryRefund($orderState, $orderStatus, $refundStatus, $amountValue);
        } elseif ($this->_sibsOrder->isCaptured()) {
            $captureStatus = $this->_paymentHelper->sibs_get_capture_refund_status($paymentStatus);
            SibsLog::info("INQUIRY - Capture status: $captureStatus");
            $this->inquiryCapture($orderState, $orderStatus, $captureStatus, $paymentType, $amountValue);
        } else {
            $this->inquiryOrder($orderState, $orderStatus, $amountValue);
        }
    }

    private function inquiryRefund($orderState, $orderStatus, $refundStatus, $amountValue)
    {
        if ($refundStatus == SibsConstants::MAGENTO_STATE_COMPLETE) {
            $this->_sibsOrder->refund($orderState, $orderStatus, $refundStatus, $amountValue, $this->_sibsOrder->getRefundedId());
        } else {
            $this->_sibsOrder->updateStatus($orderState, $orderStatus);
        }

        SibsLog::info('INQUIRY - Capture Status complete (ACK) for order #' . $this->_sibsOrder->getId());
        $this->_messageManager->addSuccessMessage(__('Capture status complete (ACK) for order #%1', $this->_sibsOrder->getId()));
    }

    private function inquiryCapture($orderState, $orderStatus, $captureStatus, $paymentType, $amountValue)
    {
        if ($paymentType != SibsConstants::SIBS_PAYMENT_TYPE_AUTH) {
            SibsLog::info('INQUIRY - Cannot capture a payment that is not an authorization for order #%1' . $this->_sibsOrder->getId());
            $this->_messageManager->addSuccessMessage(__('Cannot capture a payment that is not an authorization for order #%1', $this->_sibsOrder->getId()));

            return;
        }

        if ($captureStatus == SibsConstants::MAGENTO_STATE_COMPLETE) {
            $this->_sibsOrder->capture($orderState, $orderStatus, $captureStatus, $amountValue, $this->_sibsOrder->getCaptureId());
        } else {
            $this->_sibsOrder->updateStatus($orderState, $orderStatus);
        }

        SibsLog::info('INQUIRY - Capture Status complete (ACK) for order #' . $this->_sibsOrder->getId());
        $this->_messageManager->addSuccessMessage(__('Capture status complete (ACK) for order #%1', $this->_sibsOrder->getId()));
    }

    private function inquiryOrder($orderState, $orderStatus, $amountValue)
    {
        if ($orderStatus == SibsConstants::MAGENTO_STATE_PROCESSING) {
            $this->_sibsOrder->purchase($orderState, $orderStatus, $amountValue);
        } else {
            $this->_sibsOrder->updateStatus($orderState, $orderStatus);
        }

        SibsLog::info('INQUIRY - Payment Status complete (ACK) for order #' . $this->_sibsOrder->getId());
        $this->_messageManager->addSuccessMessage(__('Payment Status complete (ACK) for order #%1', $this->_sibsOrder->getId()));
    }
}
