<?php
namespace Magento\Billdesk\Controller\Payment;

require_once(__DIR__ . '/../../vendor/autoload.php');
//require __DIR__ . '/../../../../../app/bootstrap.php';

use Exception;
use Magento\Framework\App\Action\Context;
use Magento\Framework\View\Result\PageFactory;
use Magento\Checkout\Model\Session;
use Magento\Billdesk\Model\Config as MagentoConfig;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\FirePHPHandler;
use \Magento\Framework\Controller\Result\JsonFactory;
use Magento\Framework\App\CsrfAwareActionInterface;
use Magento\Framework\App\RequestInterface;
use Magento\Framework\App\Request\InvalidRequestException;
use io\billdesk\client\hmacsha256\JWESymmetricHelper;
use io\billdesk\client\hmacsha256\Config as BilldeskClientConfig;
use Magento\Quote\Api\CartManagementInterface;
use Magento\Framework\App\ObjectManager;
use PayPal\Braintree\Block\Adminhtml\Virtual\Script;
use Magento\Sales\Model\Order;
use Magento\Quote\Model\QuoteRepository;
use Magento\Sales\Model\OrderRepository;
use Magento\Quote\Api\CartRepositoryInterface;
use Magento\Quote\Model\Quote\Item;
use Magento\Quote\Model\QuoteIdMaskFactory;
use Magento\Sales\Model\OrderFactory;
use Magento\Framework\App\Bootstrap;
use Magento\Quote\Model\QuoteManagement;
use Magento\Sales\Api\Data\OrderItemInterfaceFactory;

use function GuzzleHttp\Promise\each;
use Magento\Sales\Model\Service\OrderService;
use Magento\Catalog\Model\Product;

class OrderProcessWithoutChildWindow extends \Magento\Billdesk\Controller\BaseController implements CsrfAwareActionInterface
{
    protected $_pageFactory;
    protected $_config;
    protected $_jsonResultFactory;
    protected $cartManagement;
    protected $quoteItem;
    protected $_itemModel;
    protected $quoteIdMaskFactory;
    protected $orderFactory;
    protected $orderService;
    protected $product;
    protected $_checkoutSession;
    protected $sessionManager;
    protected $cart;
    protected $quoteRepository;
    protected $repository;
    protected $jsonResultFactory;
    protected $_directory;
    protected $objectManagement;
    protected $orderRepository;
    protected $_resources;
    protected $objectManager;
    protected $messageManager;
    protected $quoteManagement;
    protected $orderItemInterfaceFactory;



    public function __construct(
        Context $context,
        PageFactory $pageFactory,
        \Magento\Customer\Model\Session $customerSession,
        \Magento\Checkout\Model\Session $checkoutSession,
        \Magento\Quote\Api\CartManagementInterface $cartManagement,
        \Magento\Framework\Session\SessionManagerInterface $sessionManager,
        \Magento\Checkout\Model\Cart $cart,
        \Magento\Quote\Model\QuoteRepository $quoteRepository,
        \Magento\Quote\Api\CartRepositoryInterface $cartRepository,
        MagentoConfig $config,
        JsonFactory $jsonResultFactory,
        \Magento\Quote\Model\Quote\Item $quoteItem,
        \Magento\Quote\Model\Quote\Item $itemModel,
        \Magento\Sales\Model\OrderRepository $orderRepository,
        QuoteIdMaskFactory $quoteIdMaskFactory,
        OrderFactory $orderFactory,
        \Magento\Quote\Model\QuoteManagement $quoteManagement,
        \Magento\Sales\Api\Data\OrderItemInterfaceFactory $orderItemInterfaceFactory,
        OrderService $orderService,
        Product $product

    ) {
        parent::__construct($context, $pageFactory, $customerSession, $checkoutSession);
        $this->_pageFactory = $pageFactory;
        $this->_config = $config;
        $this->_checkoutSession = $checkoutSession;
        $this->customerSession = $customerSession;
        $this->cartManagement  = $cartManagement;
        $this->sessionManager = $sessionManager;
        $this->cart = $cart;
        $this->quoteRepository = $quoteRepository;
        $this->repository = $cartRepository;
        $this->jsonResultFactory = $jsonResultFactory;
        $this->_directory = ObjectManager::getInstance()->get('\Magento\Framework\Filesystem\DirectoryList');
        $this->objectManagement   = \Magento\Framework\App\ObjectManager::getInstance();
        $this->quoteItem = $quoteItem;
        $this->_itemModel = $itemModel;
        $this->orderRepository = $orderRepository;
        $this->quoteIdMaskFactory = $quoteIdMaskFactory;
        $this->orderFactory = $orderFactory;
        $this->quoteManagement = $quoteManagement;
        $this->orderItemInterfaceFactory = $orderItemInterfaceFactory;
        $this->orderService = $orderService;
        $this->product = $product;
    }


    public function createCsrfValidationException(RequestInterface $request): ?InvalidRequestException
    {
        return null;
    }

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

    public function execute()
    {
        $log = new Logger('name');
        $log->pushHandler(new StreamHandler($this->_directory->getPath('log') . '/BillDesk/magento_billdesk_' . Date('Y_m_d') . '.log'));

        $this->_resources = ObjectManager::getInstance()->get('Magento\Framework\App\ResourceConnection');
        $connection = $this->_resources->getConnection();
        $Table_name = $this->_resources->getTableName('billdesk_payment_transation');

        $config = $this->_config;
        //$merchant_key    = $config->getConfigData($config::MERCHANT_KEY);
        $client_id        = $config->getConfigData($config::CLIENT_ID);

        $encryptionKey = $config->getConfigData($config::JOSE_ENCRYPTION_KEY);
        $encryptionKeyId = $config->getConfigData($config::KEY_ID);//"HMAC";
        $signingKey = $config->getConfigData($config::JOSE_SIGNING_KEY);
        $signingKeyId = "AES_DIR";

        $transaction_response = (isset($_POST['transaction_response'])) ? $_POST['transaction_response'] : null;
        // $txn_status = (isset($_POST['status'])) ? $_POST['status'] : null;

        $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
        $customer_Session = $objectManager->get('Magento\Customer\Model\Session');

        $storeManager = $objectManager->get(\Magento\Store\Model\StoreManagerInterface::class);

        $currentStoreId = $storeManager->getStore()->getStoreId();
        $log->info('Current store id: ', [$currentStoreId]);

        $cart = $objectManager->get('\Magento\Checkout\Model\Cart');
        $log->info('Cart Id: ', [$cart->getQuote()->getId()]);
       

        $cart = $objectManager->get('\Magento\Checkout\Model\Cart');
        $log->info('Cart Id: ', [$cart->getQuote()->getId()]);
        // $grandTotal = $cart->getQuote()->getGrandTotal();
        $log->info('Transation response by post:  ', [$transaction_response]);

        if ($transaction_response != null && $transaction_response != 'N') {

            try {
                    $client = new JWESymmetricHelper(
                        $encryptionKey,
                        $client_id,
                        $encryptionKeyId,
                        $log,
                        $signingKey,
                        $signingKeyId
                    );

                    if (empty($transaction_response)) {
                        $log->error('Missing transaction_response in request');
                        throw new \Exception('transaction_response is empty');
                    }

                    $log->debug('Raw transaction_response: ' . $transaction_response);

                    $jws = $client->verifyAndDecrypt($transaction_response);

                    if (!$jws) {
                        $log->error('verifyAndDecrypt returned empty or null');
                        throw new \Exception('Decryption failed');
                    }

                    $log->debug('Decrypted JWS payload: ' . $jws);

                       $txn = json_decode($jws, false); 
                    if (json_last_error() !== JSON_ERROR_NONE) {
                        $log->error('JSON decode error: ' . json_last_error_msg());
                        throw new \Exception('Failed to parse decrypted response');
                    }

                    $log->info('Parsed transaction object:', ['txn' => $txn]);
                    $log->info('Parsed transaction object associative array:', (array) $txn);

                } catch (\Throwable $e) {
                    $log->error('Exception in BillDesk response handling: ' . $e->getMessage());
                    throw $e; // rethrow if you want it to bubble up
                }


            $sql = "INSERT INTO " . $Table_name . "(orderid,transactionid,transaction_error_type,payment_method_type,transaction_date,transaction_error_code,currency,auth_status,transaction_error_desc,charge_amount) VALUES ('$txn->orderid','$txn->transactionid','$txn->transaction_error_type','$txn->payment_method_type','$txn->transaction_date','$txn->transaction_error_code','$txn->currency','$txn->auth_status','$txn->transaction_error_desc','$txn->charge_amount')";
            $connection->query($sql);
            $quote = $this->quoteRepository->get($txn->additional_info->additional_info1);

            $log->info('Price : ' . $quote->getgrand_total());
            $log->info('Email address from quote: ', [$quote->getBillingAddress()->getEmail()]);
            $log->info('Email address by checkout session: ', [$this->customerSession->getCustomerEmailAddress()]);
            $email     = $quote->getBillingAddress()->getEmail() ?? 'null';
            if (round($txn->amount, 2) >= round($quote->getgrand_total(), 2)) {
                if ($txn->auth_status === '0300') {
                    $log->info('Transation successfull with quote Id: ', [$txn->additional_info->additional_info1]);
                    $log->info('Customer is logged in with id: ', [$txn->additional_info->additional_info3]);
                        if ($txn->additional_info->additional_info2 === "false") {
                        $quote->setCheckoutMethod($this->cartManagement::METHOD_GUEST);
                        $quote->setCustomerEmail($email);
                        $order_id = $this->cartManagement->placeOrder($txn->additional_info->additional_info1);
                        $log->info('Place Order successfull with order id: ', [$order_id]);

                        $order = $objectManager->create('\Magento\Sales\Model\Order')->load($order_id);
                        $orderState = Order::STATE_PROCESSING;
                        $order->setState($orderState)->setStatus(Order::STATE_PROCESSING);
                        $order->save();

                        $payment = $order->getPayment();
                        $paymentId = $txn->transactionid;
                        $payment->setLastTransId($paymentId)->setTransactionId($paymentId)->setIsTransactionClosed(true)->setShouldCloseParentTransaction(true);
                        $payment->setParentTransactionId($payment->getTransactionId());
                        $transaction = $payment->addTransaction(\Magento\Sales\Model\Order\Payment\Transaction::TYPE_AUTH, null, true, "");
                        $transaction->setIsClosed(true);
                        $transaction->save();
                        $order->save();
                        $this->orderRepository->save($order);

                        $this->objectManager = \Magento\Framework\App\ObjectManager::getInstance();
                        $quote = $this->objectManager->get('Magento\Quote\Model\Quote')->load($order->getQuoteId());
                        $quote->setIsActive(false)->save();

                        return $this->_redirect('checkout/onepage/success');
                    } else {
                        $customerFactory = $objectManager->get('\Magento\Customer\Model\CustomerFactory');
                        $customer = $customerFactory->create();
                        $customer->load($txn->additional_info->additional_info3); // load customer by using ID
                        $customerSession = $objectManager->get('Magento\Customer\Model\Session');
                        $customerSession->setCustomerAsLoggedIn($customer);


                        $order_id = $this->cartManagement->placeOrder($txn->additional_info->additional_info1);
                        $log->info('Place Order successfull with order id: ', [$order_id]);

                        $order = $objectManager->create('\Magento\Sales\Model\Order')->load($order_id);
                        $orderState = Order::STATE_PROCESSING;
                        $order->setState($orderState)->setStatus(Order::STATE_PROCESSING);
                        $order->save();

                        $payment = $order->getPayment();
                        $paymentId = $txn->transactionid;
                        $payment->setLastTransId($paymentId)->setTransactionId($paymentId)->setIsTransactionClosed(true)->setShouldCloseParentTransaction(true);
                        $payment->setParentTransactionId($payment->getTransactionId());
                        $transaction = $payment->addTransaction(\Magento\Sales\Model\Order\Payment\Transaction::TYPE_AUTH, null, true, "");
                        $transaction->setIsClosed(true);
                        $transaction->save();
                        $order->save();
                        $this->orderRepository->save($order);

                        $this->objectManager = \Magento\Framework\App\ObjectManager::getInstance();
                        $quote = $this->objectManager->get('Magento\Quote\Model\Quote')->load($order->getQuoteId());
                        $quote->setIsActive(false)->save();

                        return $this->_redirect('checkout/onepage/success');
                    }
                } else if ($txn->auth_status === '0002') {
                    $log->info('Transation pending with quote Id: ', [$txn->additional_info->additional_info1]);
                    $log->info('Customer is logged in with id: ', [$txn->additional_info->additional_info3]);

                    if (!strcmp($txn->additional_info->additional_info2, "false")) {
                        $log->info('Customer is not loggedIn');
                        $quote->setCheckoutMethod($this->cartManagement::METHOD_GUEST);
                        $quote->setCustomerEmail($email);
                        $order_id = $this->cartManagement->placeOrder($txn->additional_info->additional_info1);
                        $log->info('Order is in pending state with order id: ', [$order_id]);
                        $this->messageManager->addError(__('Transaction Status: ' . 'PENDING PAYMENT')); 
                        $this->messageManager->addError(__('OrderId: ' . $txn->orderid));  
                        $this->messageManager->addError(__('TransationId: ' . $txn->transactionid));                   
                        $order = $objectManager->create('\Magento\Sales\Model\Order')->load($order_id);
                        $orderState = Order::STATE_PENDING_PAYMENT;
                        $order->setState($orderState)->setStatus(Order::STATE_PENDING_PAYMENT);
                        $order->save();
                        $orderModel = $this->_objectManager->get('Magento\Sales\Model\Order')->load($order_id);
                        $orderModel->setStatus(Order::STATE_PENDING_PAYMENT)->save();

                        $payment = $order->getPayment();
                        $paymentId = $txn->transactionid;
                        $payment->setLastTransId($paymentId)->setTransactionId($paymentId)->setIsTransactionClosed(true)->setShouldCloseParentTransaction(true);
                        $payment->setParentTransactionId($payment->getTransactionId());
                        $transaction = $payment->addTransaction(\Magento\Sales\Model\Order\Payment\Transaction::TYPE_AUTH, null, true, "");
                        $transaction->setIsClosed(true);
                        $transaction->save();
                        $order->save();
                        $this->orderRepository->save($order);

                        $this->objectManager = \Magento\Framework\App\ObjectManager::getInstance();
                        $quote = $this->objectManager->get('Magento\Quote\Model\Quote')->load($order->getQuoteId());
                        $quote->setIsActive(false)->save();

                        return $this->_redirect('checkout/cart');
                    } else {
                        $customerFactory = $objectManager->get('\Magento\Customer\Model\CustomerFactory');
                        $customer = $customerFactory->create();
                        $customer->load($txn->additional_info->additional_info3); // load customer by using ID
                        $customerSession = $objectManager->get('Magento\Customer\Model\Session');
                        $customerSession->setCustomerAsLoggedIn($customer);
                        $this->messageManager->addError(__('Transaction Status: ' . 'PENDING PAYMENT')); 
                        $this->messageManager->addError(__('OrderId: ' . $txn->orderid));  
                        $this->messageManager->addError(__('TransationId: ' . $txn->transactionid));  

                        $order_id = $this->cartManagement->placeOrder($txn->additional_info->additional_info1);
                        $log->info('Order pending with order id: ', [$order_id]);

                        $order = $objectManager->create('\Magento\Sales\Model\Order')->load($order_id);
                        $orderState = Order::STATE_PENDING_PAYMENT;
                        $order->setState($orderState)->setStatus(Order::STATE_PENDING_PAYMENT);
                        $order->save();

                        $payment = $order->getPayment();
                        $paymentId = $txn->transactionid;
                        $payment->setLastTransId($paymentId)->setTransactionId($paymentId)->setIsTransactionClosed(true)->setShouldCloseParentTransaction(true);
                        $payment->setParentTransactionId($payment->getTransactionId());
                        $transaction = $payment->addTransaction(\Magento\Sales\Model\Order\Payment\Transaction::TYPE_AUTH, null, true, "");
                        $transaction->setIsClosed(true);
                        $transaction->save();
                        $order->save();
                        $this->orderRepository->save($order);

                        $this->objectManager = \Magento\Framework\App\ObjectManager::getInstance();
                        $quote = $this->objectManager->get('Magento\Quote\Model\Quote')->load($order->getQuoteId());
                        $quote->setIsActive(false)->save();

                        return $this->_redirect('checkout/cart');
                    }
                } else if ($txn->auth_status === '0399') {
                    if (!strcmp($txn->additional_info->additional_info2, "false")) {
                        $this->messageManager->addError(__('Transaction Status: ' . 'PAYMENT FAILED'));
                        $this->messageManager->addError(__('Message: ' . $txn->transaction_error_desc));
                        $this->messageManager->addError(__('OrderId: ' . $txn->orderid));
                        $this->messageManager->addError(__('TransationId: ' . $txn->transactionid));
                        $this->messageManager->addError(__('Transation error Type: ' . $txn->transaction_error_type));


                        $quote->setCheckoutMethod($this->cartManagement::METHOD_GUEST);
                        $quote->setCustomerEmail($email);
                        $order_id = $this->cartManagement->placeOrder($txn->additional_info->additional_info1);

                        $order = $objectManager->create('\Magento\Sales\Model\Order')->load($order_id);
                        $orderState = Order::STATE_CANCELED;
                        $order->setState($orderState)->setStatus(Order::STATE_CANCELED);
                        $order->save();

                        $payment = $order->getPayment();
                        $paymentId = $txn->transactionid;
                        $payment->setLastTransId($paymentId)->setTransactionId($paymentId)->setIsTransactionClosed(true)->setShouldCloseParentTransaction(true);
                        $payment->setParentTransactionId($payment->getTransactionId());
                        $transaction = $payment->addTransaction(\Magento\Sales\Model\Order\Payment\Transaction::TYPE_AUTH, null, true, "");
                        $transaction->setIsClosed(true);
                        $transaction->save();
                        $order->save();
                        $this->orderRepository->save($order);

                        $this->objectManager = \Magento\Framework\App\ObjectManager::getInstance();
                        $quote = $this->objectManager->get('Magento\Quote\Model\Quote')->load($order->getQuoteId());
                        $quote->setIsActive(true)->save();

                        return $this->_redirect('checkout/cart');
                    } else {
                        $customerFactory = $objectManager->get('\Magento\Customer\Model\CustomerFactory');
                        $customer = $customerFactory->create();
                        $customer->load($txn->additional_info->additional_info3);
                        $customerSession = $objectManager->get('Magento\Customer\Model\Session');
                        $customerSession->setCustomerAsLoggedIn($customer);

                        $this->messageManager->addError(__('Transaction Status: ' . 'PAYMENT FAILED'));
                        $this->messageManager->addError(__('Message: ' . $txn->transaction_error_desc));
                        $this->messageManager->addError(__('OrderId: ' . $txn->orderid));
                        $this->messageManager->addError(__('TransationId: ' . $txn->transactionid));
                        $this->messageManager->addError(__('Transation error Type: ' . $txn->transaction_error_type));

                        $order_id = $this->cartManagement->placeOrder($txn->additional_info->additional_info1);
                        $order = $objectManager->create('\Magento\Sales\Model\Order')->load($order_id);
                        $orderState = Order::STATE_CANCELED;
                        $order->setState($orderState)->setStatus(Order::STATE_CANCELED);
                        $order->save();

                        $payment = $order->getPayment();
                        $paymentId = $txn->transactionid;
                        $payment->setLastTransId($paymentId)->setTransactionId($paymentId)->setIsTransactionClosed(true)->setShouldCloseParentTransaction(true);
                        $payment->setParentTransactionId($payment->getTransactionId());
                        $transaction = $payment->addTransaction(\Magento\Sales\Model\Order\Payment\Transaction::TYPE_AUTH, null, true, "");
                        $transaction->setIsClosed(true);
                        $transaction->save();
                        $order->save();
                        $this->orderRepository->save($order);

                        $this->objectManager = \Magento\Framework\App\ObjectManager::getInstance();
                        $quote = $this->objectManager->get('Magento\Quote\Model\Quote')->load($order->getQuoteId());
                        $quote->setIsActive(true)->save();

                        return $this->_redirect('checkout/cart');
                    }
                }
            }
            
        } else if ( $transaction_response == 'N') {
            $this->messageManager->addError(__('Message: ' . 	'Sorry we are unable to process your request.' ));
            return $this->_redirect('checkout/cart');
        }   
        else 
            {
            $this->messageManager->addError(__('Message: ' . 	'Sorry we are unable to process your request.' ));
            return $this->_redirect('checkout/cart');
        }
    }
    protected function getQuoteObject($post, $quoteId)
    {
        $log = new Logger('name');
        $log->pushHandler(new StreamHandler($this->_directory->getPath('log') . '/BillDesk/magento_billdesk_' . Date('Y_m_d') . '.log'));

        try {
            $quote = $this->quoteRepository->get($quoteId);

            $firstName = $quote->getBillingAddress()->getFirstname() ?? 'null';
            $lastName  = $quote->getBillingAddress()->getLastname() ?? 'null';
            $email     = $quote->getBillingAddress()->getEmail() ?? 'null';

            $quote->getPayment()->setMethod('billdesk');
            $log->info('Method name ');
            $store = $quote->getStore();
            $log->info('Store: ' . $store);
            if (empty($store) === true) {
                $store = $this->storeManagement->getStore();
            }
            $websiteId = $store->getWebsiteId();

            $customer = $this->objectManagement->create('Magento\Customer\Model\Customer');

            $customer->setWebsiteId($websiteId);

            $customer = $customer->loadByEmail($email);

            if ((empty($quote->getBillingAddress()->getFirstname()) === true) and
                (empty($customer->getEntityId()) === false)
            ) {
                $quote->getBillingAddress()->setCustomerAddressId($customer->getDefaultBillingAddress()['id']);
            }

            if ((empty($customer->getEntityId()) === true) or
                (empty($quote->getBillingAddress()->getCustomerId()) === true)
            ) {
                $quote->setCustomerFirstname($firstName);
                $quote->setCustomerLastname($lastName);
                $quote->setCustomerEmail($email);
                $quote->setCustomerIsGuest(true);
            }

            //skip address validation as some time billing/shipping address not set for the quote
            $quote->getBillingAddress()->setShouldIgnoreValidation(true);
            $quote->getShippingAddress()->setShouldIgnoreValidation(true);

            $quote->setStore($store);

            $quote->collectTotals();

            $quote->save();

            return $quote;
        } catch (Exception $ex) {
            $log->error('Billdesk front-end callback: Unable to update/get quote with quoteID:' . $quoteId . ', failed with error: ' . $ex->getMessage());
        }
    }
}
