<?php

namespace TbiBank\FusionPay\Controller\Api;

use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Magento\Framework\Controller\Result\JsonFactory;
use Magento\Framework\HTTP\Client\Curl;
use Magento\Sales\Api\OrderRepositoryInterface;
use Magento\Framework\UrlInterface as UrlBuilder;
use Magento\Catalog\Helper\Image as ImageHelper;
use TbiBank\FusionPay\Model\Cryptor;
use TbiBank\FusionPay\Helper\Data as FusionPayHelper;

class RegisterApplication extends Action
{
    /**
     * @var JsonFactory
     */
    private $resultJsonFactory;

    /**
     * @var OrderRepositoryInterface
     */
    private $orderRepository;

    /**
     * @var Curl
     */
    private $curlClient;

    /**
     * @var Cryptor
     */
    private $cryptor;

    /**
     * @var FusionPayHelper
     */
    private $fusionPayHelper;

    /**
     * @var string
     */
    private $tbiEndpoint;

    /**
     * @var string
     */
    private $encryptionKey;

    /**
     * @var ImageHelper
     */
    private $imageHelper;

    /**
     * @var UrlBuilder
     */
    private $urlBuilder;

    /**
     * @var string
     */
    private $resellerCode;

    /**
     * @var string
     */
    private $resellerKey;

    public function __construct(
        Context $context,
        JsonFactory $resultJsonFactory,
        OrderRepositoryInterface $orderRepository,
        Curl $curlClient,
        UrlBuilder $urlBuilder,
        ImageHelper $imageHelper,
        Cryptor $cryptor,
        FusionPayHelper $fusionPayHelper
    ) {
        parent::__construct($context);
        $this->resultJsonFactory = $resultJsonFactory;
        $this->orderRepository = $orderRepository;
        $this->curlClient = $curlClient;
        $this->urlBuilder = $urlBuilder;
        $this->imageHelper = $imageHelper;
        $this->cryptor = $cryptor;
        $this->fusionPayHelper = $fusionPayHelper;
        $this->initializeConfigurations();
    }

    /**
     * Initializes API endpoint and security configurations.
     */
    private function initializeConfigurations(): void
    {
        $this->tbiEndpoint = $this->fusionPayHelper->getConstValue('TBI_PLATFORM_URL') . "/api/RegisterApplication";
        $this->encryptionKey = $this->fusionPayHelper->getConfigValue('tbi_settings/general_settings/encryption_key');
        $this->resellerCode = $this->fusionPayHelper->getConfigValue('tbi_settings/general_settings/reseller_code');
        $this->resellerKey = $this->fusionPayHelper->getConfigValue('tbi_settings/general_settings/reseller_key');
    }

    /**
     * Main method to handle API requests.
     *
     * @return \Magento\Framework\Controller\Result\Json
     */
    public function execute(): \Magento\Framework\Controller\Result\Json
    {
        $result = $this->resultJsonFactory->create();
        $defaultErrorUrl = $this->fusionPayHelper->getConstValue('TBI_PLATFORM_URL') . '/application/error/error-notified';

        $requestData = json_decode($this->getRequest()->getContent(), true);
        if (!isset($requestData['orderID'])) {
            return $result->setData(['url' => $defaultErrorUrl, 'debug' => "no_order"]);
        }

        try {
            $order = $this->orderRepository->get($requestData['orderID']);
            $orderData = $this->prepareOrderData($order);
            $response = $this->makeApiCall($orderData);
            return $result->setData($response);
        } catch (\Exception $e) {
            return $result->setData(['url' => $defaultErrorUrl, 'debug' => $e->getMessage()]);
        }
    }

    /**
     * Prepares order data for the API call.
     *
     * @param \Magento\Sales\Api\Data\OrderInterface $order
     * @return array
     */
    protected function prepareOrderData($order)
    {
        $items = [];

        foreach ($order->getAllVisibleItems() as $item) {
            $product = $item->getProduct();
            $productImageUrl = $this->getProductImageUrl($product);
            $items[] = [
                "name" => $item->getName(),
                "qty" => (int) $item->getQtyOrdered(),
                "price" => round($item->getPriceInclTax(), 2),
                "category" => '0',
                "sku" => $item->getSku(),
                "id" => $item->getProductId(),
                "imagelink" => $productImageUrl,
                "scheme_id" => $item->getData('scheme_id'),
                "downpayment" => $item->getData('downpayment'),
                // other item details...
            ];
        }

        $billingAddress = $order->getBillingAddress();
        $shippingAddress = $order->getShippingAddress() ?: $billingAddress; // Use billing address if shipping is not available

        // Retrieving discount and shipping information
        $discountAmount = abs($order->getDiscountAmount()); // Discount amount is typically negative, so use abs() to make it positive
        $shippingAmount = $order->getShippingAmount();

        // Prefer shipping including tax when available; fallback to shipping + shipping tax amount
        $shippingInclTax = $order->getShippingInclTax();
        $shippingTaxAmount = $order->getShippingTaxAmount();
        if ($shippingInclTax && $shippingInclTax > 0) {
            $shippingPrice = round($shippingInclTax, 2);
        } else {
            $shippingPrice = round((float)$shippingAmount + (float)$shippingTaxAmount, 2);
        }

        if ($shippingPrice > 0) {
            $items[sizeof($items)] = [
                "name" => $this->fusionPayHelper->getConstValue('TBI_SHIPPING_NAME'),
                "qty" => 1,
                "price" => $shippingPrice,
                "category" => 348,
                "sku" => 348,
                "id" => 348,
                "imagelink" => '',
            ];
        }

        if ($discountAmount>0) {
            $items[sizeof($items)] = [
                "name" => $this->fusionPayHelper->getConstValue('TBI_COUPON_NAME'),
                "qty" => 1,
                "price" => -round($discountAmount, 2),
                "category" => 999,
                "sku" => 999,
                "id" => 999,
                "imagelink" => '',
            ];
        }

        $applicationData = [
            "orderid" => $order->getIncrementId(),
            "firstname" => $billingAddress->getFirstname(),
            "lastname" => $billingAddress->getLastname(),
            "email" => $billingAddress->getEmail(),
            "phone" => $billingAddress->getTelephone(),
            "deliveryaddress" => [
                "city" => $shippingAddress->getCity(),
                "streetname" => implode(' ', $shippingAddress->getStreet()),
                "postalcode" => $shippingAddress->getPostcode(),
            ],
            "items" => $items,
            "successRedirectURL" => $this->getSuccessPageUrl(),
            "failRedirectURL" => $this->getSuccessPageUrl()
        ];

        // Additional logic as per your requirements

        $result = [
            "reseller_code" => $this->resellerCode,
            "reseller_key" => $this->resellerKey,
            "data" => $this->cryptor->Encrypt(json_encode($applicationData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE), $this->encryptionKey)
        ];

        return $result;
    }

    /**
     * Makes the actual API call to the TBI endpoint.
     *
     * @param array $data
     * @return array
     */
    protected function makeApiCall($data)
    {
        $this->curlClient->addHeader("Content-Type", "application/json");
        $this->curlClient->addHeader('Expect', '');
        $this->curlClient->post($this->tbiEndpoint, json_encode($data));
    
        if ($this->curlClient->getStatus() == 200) {
            $responseBody = $this->curlClient->getBody();
            $response = json_decode($responseBody, true);
            return $response; // Adjust according to the expected response structure
        } else {
            // Handle non-200 responses appropriately
            return [
                'error' => true,
                'message' => 'API call failed with status code ' . $this->curlClient->getStatus()
            ];
        }
    }

    /**
     * Retrieves the URL for a product's base image.
     *
     * @param \Magento\Catalog\Model\Product $product
     * @return string
     */
    protected function getProductImageUrl($product)
    {
        return $this->imageHelper->init($product, 'product_base_image')->getUrl();
    }

    /**
     * Get the URL for the order success page.
     *
     * @return string
     */
    protected function getSuccessPageUrl()
    {
        // The route 'checkout/onepage/success' is typically used for the order success page in Magento.
        return $this->urlBuilder->getUrl('checkout/onepage/success', ['_secure' => true]);
    }

    
}
