<?php

namespace Sts\SmartRoute\Controller\Payment;

use Magento\Sales\Model\Order;
use Magento\Sales\Model\Order\Payment\Transaction;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\Controller\ResultFactory;
use Magento\Framework\App\CsrfAwareActionInterface;
use Magento\Framework\App\RequestInterface;
use Magento\Framework\App\Request\InvalidRequestException;
class DirectPostResponse extends \Magento\Framework\App\Action\Action implements CsrfAwareActionInterface{

    /**
     * Customer session model
     *
     * @var \Magento\Customer\Model\Session
     */
    protected $_customerSession;
    protected $resultFactory;
    protected $_scopeConfig;
    protected $_orderFactory;    
    protected $orderSender;
    protected $request;
    protected $_paymentMethod;
    protected $logger;
    protected $paymentTransactionFactory;

    const PAYMENT_STATUS_SUCCESS = '00000';

    /**
     * 
     * @param \Magento\Framework\App\Request\Http $request
     * @param \Magento\Framework\App\Action\Context $context
     * @param \Psr\Log\LoggerInterface $logger
     * @param ResultFactory $result
     * @param ScopeConfigInterface $scopeConfig
     * @param \Sts\SmartRoute\Model\PaymentMethod $paymentMethod
     */
    public function __construct(
            \Magento\Framework\App\Request\Http $request, 
            \Magento\Framework\App\Action\Context $context, 
            \Psr\Log\LoggerInterface $logger,
            ResultFactory $result,
            ScopeConfigInterface $scopeConfig,
            \Magento\Sales\Model\Order\Payment\TransactionFactory $paymentTransactionFactory,
            \Sts\SmartRoute\Model\PaymentMethod $paymentMethod            
    ) {
        $this->_request = $request;
        parent::__construct($context);
        $this->_scopeConfig = $scopeConfig;
        $this->logger = $logger;   
        $this->resultFactory = $result;
        $this->_paymentMethod = $paymentMethod;
        $this->paymentTransactionFactory = $paymentTransactionFactory;
    }


    public function execute() {

        // 4.4 Direct Post Payment Response
        // Get All Request Parameters
        $parameters = $this->_request->getParams();
        $this->logger->info('smartroute direct post response parameters: '.json_encode($parameters));
            
        $secretKey = $this->_scopeConfig->getValue('payment/smartroute/secret_key');
        
        /*@var $order Order*/
        $order = null;
        if(isset($parameters['Response_TransactionID'])){            
            $transactionFactory = $this->paymentTransactionFactory->create();
            $transaction = $transactionFactory->load($parameters['Response_TransactionID'], 'txn_id');
            if($transaction){
                $order = $transaction->getOrder();
            }
        }
        if(!$order){
            $this->messageManager->addErrorMessage('Order not found');
            return $this->_redirect('stssmartroute/payment/cancel',[                   
                    'statusDesc'=> 'Order not found',
                    'statusCode'=> ''
                ]);
        }
    
        $receivedSecurehash = $parameters["Response_SecureHash"];
        // store all response Parameters to generate Response Secure Hash, sort them
        // and get Parameters to use it later in your Code
        unset($parameters['Response_SecureHash']);
        
        ksort($parameters);
        // Now that we have the map, order it to generate secure hash and compare it with the received one        
        $responseOrderdString = $secretKey;
        foreach($parameters as $key=>$param){
            if($param !== 'null'){
                if(strpos($key,'Status')!== false){ //remove spaces from status directives
                    $param = urlencode($param);
                }
                $responseOrderdString .= $param;
            }
        }

        //log ("Response Orderd String is: " . $responseOrderdString).chr(10);

        // Generate SecureHash with SHA256
        $generatedsecureHash = hash('sha256', $responseOrderdString, false);
        // get the received secure hash from result map        
        // Now that we have the map, order it to generate secure hash and compare it with the received one
        if ($receivedSecurehash !== $generatedsecureHash) { 
               $inquiryRet = $this->_paymentMethod->processAPIInquiry($order);
               if($inquiryRet['status'] === self::PAYMENT_STATUS_SUCCESS){
                    $this->messageManager->addSuccessMessage(__($inquiryRet['statusDescription']));
                    $this->_redirect('stssmartroute/payment/paymentComplete',[                    
                        'statusCode'=> $inquiryRet['status'],
                        'statusDesc'=> __($inquiryRet['statusDescription']),
                        'TransactionId' => $parameters['Response_TransactionID'],
		        'inquiry' => 1,
                    ]);
               }else{
                    // IF they are not equal then the response shall not be accepted
                   $this->messageManager->addErrorMessage(__($inquiryRet['statusDescription']));
                    $this->_redirect('stssmartroute/payment/cancel',[               
                        'statusDesc'=> __($inquiryRet['statusDescription']),
                        'statusCode'=> '',
                        'TransactionId' => $parameters['Response_TransactionID'],
		        'inquiry' => 1,
                    ]);
               }
        }else{
            // Complete the Action get other parameters from result map and do
            // your processes
            // Please refer to The Integration Manual to see the List of The
            // Received Parameters
            $status = $parameters["Response_StatusCode"];            
            $statusDesc = $parameters['Response_StatusDescription'];            
            if($status == self::PAYMENT_STATUS_SUCCESS){
                $this->messageManager->addSuccessMessage(__($statusDesc));
                $this->_paymentMethod->markOrderAsSuccessfull($order,$parameters['Response_TransactionID']);                
                $this->_redirect('stssmartroute/payment/paymentComplete',[                    
                    'statusCode'=> $status,
                    'statusDesc'=> __($statusDesc),
                    'TransactionId' => $parameters['Response_TransactionID']
                ]);
            }else{                               
                $this->messageManager->addErrorMessage(__($statusDesc));
                $this->_redirect('stssmartroute/payment/cancel',[                    
                    'statusCode'=> $status,
                    'statusDesc'=> $statusDesc,
                    'TransactionId' => $parameters['Response_TransactionID']
                ]);
            }
        }
        
    }

    /**
     * prepare direct post methods data
     * @param Transaction $transaction
     * @param string $secureHash
     * @return array
     */
    protected function prepareDirectPostRequest(Transaction $transaction, $secureHash){
        /*@var Order $order */
        $order = $transaction->getOrder();
        $totalAmount = $this->_paymentMethod->getTotalAmountForGateway($order);
        $currencyIso = $this->_paymentMethod->getCurrencyIsoNumberFromCode($order->getBaseCurrencyCode());                        
        
        $paymentParameters = [];
        $paymentParameters["TransactionID"] = $transaction->getTxnId();
        $paymentParameters["MerchantID"] = $this->_paymentMethod->getConfigData('merchant_id');
        $paymentParameters["Amount"] = $totalAmount;
        $paymentParameters["CurrencyISOCode"] = $currencyIso;
        $paymentParameters["MessageID"] = "1";
        $paymentParameters["Quantity"] = "1";
        $paymentParameters["Channel"] = "0";

        $paymentParameters["PaymentMethod"] = "1";
         
        $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
        $getLocale = $objectManager->get('Magento\Framework\Locale\Resolver');
        $haystack  = $getLocale->getLocale(); 
        $lang = strstr($haystack, '_', true); 
        
        $paymentParameters["Language"] = $lang;
        $paymentParameters["ThemeID"] = "1000000001";
        $paymentParameters["ResponseBackURL"] = $this->urlBuilder->getUrl('stssmartroute/payment/directPostResponse');
        $paymentParameters["Version"] = "1.0";
        $paymentParameters["RedirectURL"] = $this->getConfigData('redirect_payment_url');
        // set secure hash in the requrest
        $paymentParameters["SecureHash"] = $secureHash;
            
        return $paymentParameters;
    }
    
    public function createCsrfValidationException(RequestInterface $request): ?InvalidRequestException
    {
        return null;
    }

    public function validateForCsrf(RequestInterface $request): ?bool
    {
        return true;
    }
}
