<?php

namespace Magento\Billdesk\Controller\Payment;

require_once(__DIR__ . '/../../vendor/autoload.php');

use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Psr7\Message;
use io\billdesk\client\hmacsha256\BillDeskJWEHS256Client;
use io\billdesk\client\hmacsha256\Config as BilldeskClientConfig;
use Magento\Framework\App\Action\Context;
use Magento\Framework\View\Result\PageFactory;
use Magento\Billdesk\Model\Config as MagentoConfig;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Magento\Framework\Controller\Result\JsonFactory;
use Magento\Framework\App\ObjectManager;
use Magento\Quote\Model\QuoteRepository;
use Magento\Sales\Api\OrderRepositoryInterface;
use Magento\Quote\Model\QuoteManagement;

class OrderCreate extends \Magento\Billdesk\Controller\BaseController
{
    protected $_pageFactory;
    protected $_config;
    protected $_jsonResultFactory;
    protected $customerSession;
    protected $checkoutSession;
    protected $productMetadata;
    protected $quoteRepository;
    protected $orderRepository;
    protected $jsonResultFactory;
    protected $_directory;
    protected $quoteManagement;

    public function __construct(
        Context $context,
        PageFactory $pageFactory,
        \Magento\Customer\Model\Session $customerSession,
        \Magento\Checkout\Model\Session $checkoutSession,
        MagentoConfig $config,
        JsonFactory $jsonResultFactory,
        \Magento\Framework\App\ProductMetadataInterface $productMetadata,
        QuoteRepository $quoteRepository,
        OrderRepositoryInterface $orderRepository,
        QuoteManagement $quoteManagement
    ) {
        parent::__construct($context, $pageFactory, $customerSession, $checkoutSession);
        $this->_pageFactory = $pageFactory;
        $this->_config = $config;
        $this->jsonResultFactory = $jsonResultFactory;
        $this->customerSession = $customerSession;
        $this->checkoutSession = $checkoutSession;
        $this->_directory = ObjectManager::getInstance()->get('\\Magento\\Framework\\Filesystem\\DirectoryList');
        $this->productMetadata = $productMetadata;
        $this->quoteRepository = $quoteRepository;
        $this->orderRepository = $orderRepository;
        $this->quoteManagement = $quoteManagement;
    }

    public function execute()
    {
        $log = new Logger('billdesk');
        $logPath = $this->_directory->getPath('log') . '/BillDesk';
        if (!is_dir($logPath)) {
            mkdir($logPath, 0775, true);
        }
        $log->pushHandler(new StreamHandler("{$logPath}/magento_billdesk_" . date('Y_m_d') . ".log"));
        $log->pushProcessor(function ($record) {
            $record['extra']['user'] = get_current_user();
            return $record;
        });

        try {
            $quote = $this->quoteRepository->get($this->getQuote()->getId());
            $log->info('Quote ID:', [$quote->getId()]);

            $grandTotal = $quote->getGrandTotal();
            $log->info('Quote Grand Total:', [$grandTotal]);

            $customer_Session = $this->customerSession;
            $log->info('Customer session check:', [$customer_Session->isLoggedIn()]);

            $customer_id = $customer_Session->isLoggedIn()
                ? $customer_Session->getCustomer()->getId()
                : $quote->getBillingAddress()->getEmail();

            $log->info('Resolved customer ID/email:', [$customer_id]);

            $config = $this->_config;
            $client_id     = $config->getConfigData($config::CLIENT_ID);
            $key_id     = $config->getConfigData($config::KEY_ID);
            $merchant_id   = $config->getConfigData($config::MERCHANT_ID);
            $itemcode      = $config->getConfigData($config::ITEM_CODE);
            $child_window  = $config->getConfigData($config::CHILD_WINDOW);
            $signingKey    = $config->getConfigData($config::JOSE_SIGNING_KEY);
            $encryptionKey = $config->getConfigData($config::JOSE_ENCRYPTION_KEY);
            $env           = $config->getConfigData($config::ENV_VARIABLE);
            $currencyCode  = $quote->getQuoteCurrencyCode();

            $currencyMap = [
                'INR' => '356', 'USD' => '840', 'EUR' => '978',
                'JPY' => '392', 'AUD' => '036', 'HKD' => '344',
                'MYR' => '458', 'SGD' => '702', 'NZD' => '554'
            ];
            $currency = $currencyMap[$currencyCode] ?? '356';

            $ip = $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
            $userAgent = $_SERVER['HTTP_USER_AGENT'] ?? 'unknown';

            $returnUrl = ($child_window == "true")
                ? rtrim($this->_url->getUrl('billdesk/Payment/billdeskautoclose'), "/ ")
                : $this->_url->getUrl('billdesk/Payment/orderprocesswithoutchildwindow');

            $baseUrl = ($env == "UAT") ? 'https://uat1.billdesk.com/u2' : 'https://api.billdesk.com';

            $clientConfig = new BilldeskClientConfig();
            $clientConfig->setMerchantId($merchant_id);
            $clientConfig->setClientId($client_id);
            $clientConfig->setEncryptionKeyBase64($encryptionKey);
            $clientConfig->setSigningKeyBase64($signingKey);
            $clientConfig->setEncryptionKeyId($key_id);
            $clientConfig->setSigningKeyId("AES_DIR");

            $client = new BillDeskJWEHS256Client($clientConfig, $baseUrl);

            $request = [
                'mercid' => $merchant_id,
                'orderid' => uniqid(),
                'amount' => (float) $grandTotal,
                'order_date' => date(DATE_W3C),
                'currency' => $currency,
                'ru' => $returnUrl,
                'itemcode' => $itemcode,
                'device' => [
                    'init_channel' => 'internet',
                    'ip' => $ip,
                    'user_agent' => $userAgent
                ],
                'additional_info' => [
                    'additional_info1' => $quote->getId(),
                    'additional_info2' => $customer_Session->isLoggedIn() ? 'true' : 'false',
                    'additional_info3' => $customer_id,
                    'additional_info4' => $quote->getId(),
                    'additional_info8' => '_bd_platform_magento_' . $this->productMetadata->getVersion(),
                    'additional_info9' => '_bd_plugin_version_1.1.0',
                    'additional_info10' => '_bd_source_ecomplugin_magento',
                ]
            ];

            $log->info('Outgoing BillDesk order request:', $request);

            $response = $client->createOrder($request);
            $resultArray = $response->getResponse();
            $log->info('Received response from BillDesk:', $resultArray);

            $resultJson = $this->jsonResultFactory->create();
            return $resultJson->setData($resultArray);

        } catch (RequestException $ex) {
            $log->error('RequestException occurred:', [
                'message' => $ex->getMessage(),
                'response' => $ex->hasResponse() ? Message::toString($ex->getResponse()) : 'No response'
            ]);
            throw $ex;
        } catch (\Exception $e) {
            $log->error('General exception occurred:', ['message' => $e->getMessage()]);
            throw $e;
        }
    }
}
