<?php

namespace Leadlion\SalesOrder\Controller\Adminhtml\Order\Edit;

use Exception;
use Magento\Framework\App\ResponseInterface;
use Magento\Framework\Controller\Result\Json;
use Magento\Framework\Controller\ResultInterface;
use Magento\Framework\Exception\LocalizedException;
use Magento\Sales\Model\Order;
use Magento\Sales\Model\Order\Payment;
use Mageplaza\EditOrder\Model\Logs;
use Laminas\Uri\Uri;

class Save extends \Mageplaza\EditOrder\Controller\Adminhtml\Order\Edit\Save
{
    /**
     * @return ResponseInterface|Json|ResultInterface
     * @throws LocalizedException
     */
    public function execute()
    {
        $result         = $this->resultJsonFactory->create();
        $orderId        = $this->getRequest()->getParam('order_id');
        $order          = $this->getOrder();
        $newData        = $this->getNewData();
        $oldData        = $this->getOldData();
        $oldPaymentData = $this->getOldPaymentData();
        $oldTotalData   = [
            'subtotal'        => $order->getBaseSubtotal(),
            'shipping_amount' => $order->getBaseShippingAmount(),
            'tax_amount'      => $order->getBaseTaxAmount(),
            'discount_amount' => $order->getBaseDiscountAmount(),
            'grand_total'     => $order->getBaseGrandTotal(),
            'total_paid'      => $order->getBaseTotalPaid(),
            'total_refund'    => $order->getBaseTotalRefunded(),
            'total_due'       => $order->getBaseTotalDue(),
        ];

        $resultData = [];
        $diff       = $this->_helperData->arrayDifferent($newData, $oldData);
//        if (empty($diff)) {
//            $resultData['items'] = [
//                'error'   => true,
//                'message' => __('No change to Save to the Order')
//            ];
//
//            return $result->setData($resultData);
//        }

        /** check if empty item */
        if (isset($oldData['item']) && !isset($newData['item'])) {
            $resultData['items'] = [
                'error'   => true,
                'message' => __('There must always be items')
            ];

            return $result->setData($resultData);
        }

        /** save order data */
        if ($orderId && (isset($newData['order']) || isset($newData['item']))) {
            if (isset($newData['order']['shipping_method']) || isset($newData['method_detail'])) {
                $diff['order']['shipping_method'] = true;
            }
            $resultData = $this->setPostData($newData, $diff);
        }

        if (isset($newData['payment'])) {
            $resultData['payment_method'] = $this->editPaymentMethod($order, $newData['payment']);
        }

        /** result error */
        foreach ($resultData as $key => $value) {
            if (isset($resultData[$key]['error'])) {
                $resultData = [
                    $key => $value
                ];
            }
        }

        if (!isset($resultData['shipping_method']['error'])
            && !isset($resultData['info']['error'])
            && !isset($resultData['items']['error'])
        ) {
            /** @var Logs $log */
            $log     = $this->logsFactory->create();
            $logData = $this->getLogData($oldPaymentData, $oldTotalData, $newData, $oldData, $diff);
            try {
                $log->addData($logData)->save();
            } catch (Exception $e) {
                $this->_logger->critical($e->getMessage());
            }
        }

        $result->setData($resultData);

        return $result;
    }

    /**
     * @param Order $order
     * @param array $newData
     *
     * @return array
     */
    public function editPaymentMethod($order, $newData)
    {
        $paymentId   = 0;
        $paymentData = $newData;

        if ($order->getPayment()) {
            $paymentId = $order->getPayment()->getEntityId();
        }
        /** @var Payment $payment */
        $payment = $this->paymentFactory->create();
        $this->paymentResource->load($payment, $paymentId);
        $order->setPayment($payment);
        $payment->addData($paymentData);
        $payment->setAdditionalInformation('instructions', $this->getInstructions($paymentData['method']));
        $payment->setAdditionalInformation('method_title', $this->getMethodTitle($paymentData['method']));
        
        try {
            $payment->save();
            $this->messageManager->addSuccessMessage(__('This order has been updated!'));
            $resultData = ['success' => $this->getPaymentHtml($order)];
        } catch (Exception $e) {
            $resultData['payment_save_error'] = [
                'error'   => true,
                'message' => $e->getMessage()
            ];
        }

        return $resultData;
    }

    protected function getMethodTitle($code)
    {
        $path = 'payment/' . $code . '/title';
        $_scopeConfig = \Magento\Framework\App\ObjectManager::getInstance()->get(\Magento\Framework\App\Config\ScopeConfigInterface::class);
        $escaper = \Magento\Framework\App\ObjectManager::getInstance()->get(\Magento\Framework\Escaper::class);

        $instructions = $_scopeConfig->getValue($path, \Magento\Store\Model\ScopeInterface::SCOPE_STORE, 0);
        return nl2br($escaper->escapeHtml($instructions));
    }

    /**
     * Get instructions text from config
     *
     * @param string $code
     * @return string
     */
    protected function getInstructions($code)
    {
        $path = 'payment/' . $code . '/instructions';
        $_scopeConfig = \Magento\Framework\App\ObjectManager::getInstance()->get(\Magento\Framework\App\Config\ScopeConfigInterface::class);
        $escaper = \Magento\Framework\App\ObjectManager::getInstance()->get(\Magento\Framework\Escaper::class);

        $instructions = $_scopeConfig->getValue($path, \Magento\Store\Model\ScopeInterface::SCOPE_STORE, 0);
        return nl2br($escaper->escapeHtml($instructions));
    }
}
