<?php
/**
 * Copyright © Magento. All rights reserved.
 * See COPYING.txt for license details.
 */

namespace Netopia\Netcard\Block;

use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\View\Element\Template;
use Magento\Framework\View\Element\Template\Context;
use Magento\Checkout\Model\Session;
use Magento\Customer\Model\Session as CustomerSession;
use Magento\Framework\App\ResourceConnection;
use Magento\Sales\Model\Order;
use Magento\Quote\Model\QuoteFactory;
use Magento\Framework\Module\Dir\Reader;
use Netopia\Netcard\Mobilpay\Payment\MobilpayPaymentInvoice;
use Netopia\Netcard\Mobilpay\Payment\Request\MobilpayPaymentRequestCard;
use Netopia\Netcard\Mobilpay\Payment\MobilpayPaymentAddress;
use Magento\Framework\Module\Dir;

/**
 * Class Redirect
 * To handel Redirect from Magento to Sandbox
 *
 * @package Netopia\Netcard\Block
 */
class Redirect extends Template
{
    protected $_storeManager;
    protected $_checkoutSession;
    protected $_scopeConfig;
    protected $_orderFactory;
    protected $_resource;
    protected $_moduleReader;
    protected $quoteFactory;
    protected $_customerSession;

    /**
     * @var MobilpayPaymentRequestCard
     */
    protected $mobilpayPaymentRequestCard;
    /**
     * @var MobilpayPaymentInvoice
     */
    protected $mobilpayPaymentInvoice;
    /**
     * @var Payment\MobilpayPaymentAddress
     */
    protected $mobilpayPaymentAddress;

    /**
     * Redirect constructor.
     *
     * @param Context $context
     * @param Session $session
     * @param ResourceConnection $resource
     * @param Order $orderFactory
     * @param QuoteFactory $quoteFactory
     * @param Reader $reader
     * @param array $data
     */
    public function __construct(
        Context            $context,
        Session            $session,
        CustomerSession    $customerSession,
        ResourceConnection $resource,
        Order              $orderFactory,
        QuoteFactory       $quoteFactory,
        Reader             $reader,
        array              $data)
    {
        $this->_resource = $resource;
        $this->_checkoutSession = $session;
        $this->_customerSession = $customerSession;
        $this->_orderFactory = $orderFactory;
        $this->quoteFactory = $quoteFactory;
        $this->_moduleReader = $reader;
        parent::__construct($context, $data);
    }

    /**
     * @throws NoSuchEntityException
     * @throws LocalizedException
     */
    public function getOrder()
    {
        $order = $this->_checkoutSession->getLastRealOrder();

        try {
            $customerId = $this->_checkoutSession->getQuote()->getCustomerId();
        } catch (\Exception $e) {
            $customerId = -1;
        }

        if (is_null($order) || !$order->getId()) {
            $connection = $this->_resource->getConnection(\Magento\Framework\App\ResourceConnection::DEFAULT_CONNECTION);
            $tblSalesOrder = $this->_resource->getTableName('sales_order');
            $tblQuoteIdMask = $this->_resource->getTableName('quote_id_mask');
            $quoteId = $this->_checkoutSession->getQuoteId();

            if (empty($quoteId)) {
                $quoteId = $this->getRealQuoteId($this->getRequest()->getParam('quote'));
            }

            if (empty($quoteId)) {
                return null;
            }

            if (is_numeric($quoteId)) {
                $sqlQuery = $connection->select()
                    ->from($tblSalesOrder, ['entity_id', 'customer_id'])
                    ->where('quote_id = ?', (int)$quoteId)
                    ->order('entity_id DESC')
                    ->limit(1);
            } else {
                $sqlQuery = $connection->select()
                    ->from(['so' => $tblSalesOrder], ['entity_id', 'customer_id'])
                    ->join(
                        ['qim' => $tblQuoteIdMask],
                        'so.quote_id = qim.quote_id',
                        []
                    )
                    ->where('qim.masked_id = ?', $quoteId)
                    ->order('so.entity_id DESC')
                    ->limit(1);
            }

            $orderData = $connection->fetchRow($sqlQuery);

            if (!$orderData) {
                return null;
            }

            if ($customerId && $orderData['customer_id'] && (int)$orderData['customer_id'] !== (int)$customerId) {
                return null;
            }

            return $this->_orderFactory->load((int)$orderData['entity_id']);
        }

        if ($order->getCustomerId() && $order->getCustomerId() != $this->_customerSession->getCustomerId()) {
            return null;
        }

        return $order;
    }


    public function getFormData()
    {
        $e = null;
        $moduleDirectory = $this->_moduleReader->getModuleDir(Dir::MODULE_ETC_DIR, 'Netopia_Netcard');
        $filePath = $moduleDirectory . DIRECTORY_SEPARATOR . "certificates" . DIRECTORY_SEPARATOR;

        $order = $this->getOrder();

        if (!$order) {
            $result['status'] = 0;
            $result['message'] = 'Order not found';
            return $result;
        }

        $billing = $order?->getBillingAddress();
        if (!$billing) {
            $billing = $order->getQuote()?->getBillingAddress();
        }
        $result = [];

        try {
            $objPmReqCard = new MobilpayPaymentRequestCard();
            $objPmReqCard->signature = $this->getConfigData('auth/signature');

            // Get Public Key filename
            $mode = $this->getConfigData('mode/is_live') ? "live." : "sandbox.";
            if ($this->getConfigData('mode/is_live')) {
                $livePublicKey = $this->getConfigData('mode/live_public_key');
                if (!is_null($livePublicKey) && file_exists($filePath . $livePublicKey)) {
                    $x509FilePath = $filePath . $livePublicKey;
                } else {
                    $x509FilePath = $moduleDirectory . DIRECTORY_SEPARATOR . "certificates" . DIRECTORY_SEPARATOR . $mode . $objPmReqCard->signature . ".public.cer";
                }
            } else {
                $sandboxPublicKey = $this->getConfigData('mode/sandbox_public_key');
                if (!is_null($sandboxPublicKey) && file_exists($filePath . $sandboxPublicKey)) {
                    $x509FilePath = $filePath . $sandboxPublicKey;
                } else {
                    $x509FilePath = $moduleDirectory . DIRECTORY_SEPARATOR . "certificates" . DIRECTORY_SEPARATOR . $mode . $objPmReqCard->signature . ".public.cer";
                }
            }


            $objPmReqCard->orderId = $order->getId();
            /**
             * Add timestamp to OrderId
             */
            $objPmReqCard->orderId = $objPmReqCard->orderId . '_T_' . time();

            $objPmReqCard->returnUrl = $this->getUrl('netopia/payment/success');
            $objPmReqCard->confirmUrl = $this->getUrl('netopia/payment/ipn');
            $objPmReqCard->cancelUrl = $this->getUrl('netopia/payment/cancel');


            // Add invoice info to Obj
            $objPmReqCard->invoice = new MobilpayPaymentInvoice();

            $objPmReqCard->invoice->currency = $order->getBaseCurrencyCode();
            $objPmReqCard->invoice->amount = $order->getBaseGrandTotal();

            $cart_description = $this->getConfigData('description');
            if ($cart_description != '') {
                $objPmReqCard->invoice->details = $cart_description;
            } else {
                $objPmReqCard->invoice->details = "Netopia - Magento 2 - Default description";
            }

            // Add billing address info to Obj
            $billingAddress = new MobilpayPaymentAddress();
            $company = $billing?->getCompany();
            if (!empty($company)) {
                $billingAddress->type = 'company';
            } else {
                $billingAddress->type = 'person';
            }
            $billingAddress->firstName = $billing->getFirstname();
            $billingAddress->lastName = $billing->getLastname();
            $billingAddress->country = $billing->getCountryId();

            $billingAddress->city = $billing->getCity();
            $billingAddress->zipCode = $billing->getPostcode();
            $billingAddress->state = $billing->getRegion();
            $billingAddress->address = implode(', ', $billing->getStreet());
            $billingAddress->email = $billing->getEmail();
            $billingAddress->mobilePhone = $billing->getTelephone();

            $objPmReqCard->invoice->setBillingAddress($billingAddress);

            // Missing shiping address info to Obj

            // Add Params in Obj
            $cardSummaryArr = array();
            $cardAllItems = $order->getAllVisibleItems();
            foreach ($cardAllItems as $item) {
                $cardItem['name'] = $item->getName();
                $cardItem['price'] = $item->getPrice();
                $cardItem['quantity'] = $item->getQtyOrdered();
                $cardItem['short_description'] = !is_null($item->getDescription()) || !empty($item->getDescription()) ? substr($item->getDescription(), 0, 100) : 'no description';
                $cardSummaryArr[] = $cardItem;
            }

            $cartSummaryJson = json_encode($cardSummaryArr);
            $objPmReqCard->params = array(
                "version" => "1.0.1",
                "api" => "1.0",
                "platform" => "Magento 2.4",
                "cartSummary" => $cartSummaryJson
            );


            $objPmReqCard->encrypt($x509FilePath);
        } catch (\Exception $e) {
            $result['status'] = 0;
            $result['message'] = $e->getMessage();
        }

        if (!($e instanceof \Exception)) {
            $result['status'] = 1;
            $result['data'] = $objPmReqCard->getEncData();
            $result['form_key'] = $objPmReqCard->getEnvKey();
            $result['cipher'] = $objPmReqCard->getCipher();
            $result['iv'] = $objPmReqCard->getIv();
            $result['billing'] = $billing->getData();

        } else {
            $result['status'] = 0;
            $result['message'] = $e->getMessage();
        }

        return $result;
    }

    public function getConfigData($field)
    {
        $str = 'payment/net_card/' . $field;
        return $this->_scopeConfig->getValue($str);
    }


    public function getRealQuoteId($ntpQuoteId)
    {
        $expArr = explode('_QT_', $ntpQuoteId);
        return $expArr[0];
    }
}
