<?php

namespace FiloBlu\Storelocator\Controller\PickUpInStore;

use Exception;
use FiloBlu\Storelocator\Helper\Data;
use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Magento\Framework\App\Area;
use Magento\Framework\Controller\Result\Json;
use Magento\Framework\Controller\Result\JsonFactory;
use Magento\Framework\Controller\ResultInterface;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\Mail\Template\TransportBuilder;
use Magento\Framework\Stdlib\DateTime\DateTime;
use Magento\Framework\Translate\Inline\StateInterface;
use Magento\Rma\Helper\Data as RmaHelperData;
use Magento\Sales\Api\Data\OrderInterface;
use Magento\Sales\Api\Data\OrderInterfaceFactory;
use Magento\Sales\Model\Order;
use Magento\Sales\Model\Order\Address\Renderer;
use Magento\Store\Model\StoreManagerInterface;
use Psr\Log\LoggerInterface;

/**
 *
 */
class ConfirmAction extends Action
{
    /**
     * @var Data
     */
    protected $helper;
    /**
     * @var OrderInterfaceFactory
     */
    protected $orderFactory;
    /**
     * @var StoreManagerInterface
     */
    protected $storeManager;
    /**
     * @var DateTime
     */
    protected $date;
    /**
     * @var JsonFactory
     */
    protected $resultJsonFactory;
    /**
     * @var StateInterface
     */
    protected $inlineTranslation;
    /**
     * @var TransportBuilder
     */
    protected $transportBuilder;
    /**
     * @var RmaHelperData
     */
    protected $rmaHelperData;
    /**
     * @var LoggerInterface
     */
    protected $logger;

    /**
     * @param Context $context
     * @param JsonFactory $resultJsonFactory
     * @param Data $helper
     * @param OrderInterfaceFactory $orderFactory
     * @param DateTime $date
     * @param StoreManagerInterface $storeManager
     * @param StateInterface $inlineTranslation
     * @param TransportBuilder $transportBuilder
     * @param RmaHelperData $rmaHelperData
     * @param LoggerInterface $logger
     */
    public function __construct(
        Context $context,
        JsonFactory $resultJsonFactory,
        Data $helper,
        OrderInterfaceFactory $orderFactory,
        DateTime $date,
        StoreManagerInterface $storeManager,
        StateInterface $inlineTranslation,
        TransportBuilder $transportBuilder,
        RmaHelperData $rmaHelperData,
        LoggerInterface $logger
    )
    {
        $this->resultJsonFactory = $resultJsonFactory;
        $this->helper = $helper;
        $this->orderFactory = $orderFactory;
        $this->date = $date;
        $this->storeManager = $storeManager;
        $this->inlineTranslation = $inlineTranslation;
        $this->transportBuilder = $transportBuilder;
        $this->rmaHelperData = $rmaHelperData;
        $this->logger = $logger;
        parent::__construct($context);
    }

    /**
     * @return Json|ResultInterface|void
     * @throws Exception
     */
    public function execute()
    {
        $hash = $this->getRequest()->getParam('hash');
        $storeId = $this->storeManager->getStore()->getId();

        if (!$hash || !$this->helper->getPickupInStoreEnabled($storeId)) {
            $this->_forward('noRoute');
            return;
        }

        /** @var OrderInterface|Order $order */
        $order = $this->helper->getOrderByHash($hash);

        if ($order->getId()) {
            $order->setPickupInStoreConfirmDate($this->date->gmtDate());
            $order->save();
            $this->updateOrder($order);
            $this->sendMail($order);
            $resultJson = $this->resultJsonFactory->create();
            $resultJson->setData(
                [
                    'message' => __('You confirmed that the order ') . $order->getIncrementId() . __(
                            ' was withdrawn by the customer.'
                        )
                ]
            );
            $this->_eventManager->dispatch('filoblu_storelocator_pickupinstore_confirm', ['order' => $order]);

            return $resultJson;
        }

        $this->_forward('noRoute');
    }

    /**
     * @param $order
     * @return void
     */
    public function updateOrder($order)
    {
        $order->setState(Order::STATE_COMPLETE, true);
        $order->setStatus('complete_in_store');
        $order->addStatusToHistory(
            $order->getStatus(),
            'Pick Up In Store - Order processed successfully with reference: Complete'
        );
        $order->save();
    }

    /**
     * @param $order
     * @param null $rma
     * @return void
     * @throws NoSuchEntityException
     */
    public function sendMail($order, $rma = null)
    {
        $storeId = $order->getStoreId();

        if (!$this->helper->getConfig('carriers/pickupinstore/email_after_collect_enabled', $storeId)) {
            return;
        }

        $this->inlineTranslation->suspend();

        $billingAddress = $order->getBillingAddress();

        $templateVars = [
            'order' => $order,
            'order_id'                   => $order->getId(),
            'order_increment_id'         => $order->getIncrementId(),
            'order_is_virtual'           => $order->getIsVirtual(),
            'order_is_not_virtual'       => !$order->getIsVirtual(),
            'order_store_id'             => $order->getStoreId(),
            'order_pickup_in_store_hash' => $order->getPickupInStoreHash(),
            'order_email_customer_note'  => $order->getEmailCustomerNote(),
            'billing' => $billingAddress,
            'payment_html' => $this->helper->getPaymentHtml($order),
            'store' => $order->getStore(),
            'formattedShippingAddress' => $this->helper->getFormattedShippingAddress($order),
            'formattedBillingAddress' => $this->helper->getFormattedBillingAddress($order),
            'order_data'              => [
                'pickup_in_store_hash' => $order->getData('pickup_in_store_hash'),
                'id'                   => $order->getId(),
                'increment_id'         => $order->getIncrementId(),
                'is_not_virtual'       => !$order->getIsVirtual(),
                'store_id'             => $order->getStoreId(),
                'email_customer_note'  => $order->getEmailCustomerNote(),
            ]
        ];

        if ($this->helper->getReturnToStoreEnabled($storeId)) {
            if ($rma) {
                $storeId = $rma->getReturnToStoreId();

                if ($storeId) {
                    $data = $this->helper->getStoreDetails($storeId);
                    $returnAddress = $this->rmaHelperData->getReturnAddress('html', $data, $storeId);

                    $templateVars['formattedShippingAddress'] = $returnAddress;
                    $templateVars['rma_data']  = [
                        'return_to_store_hash' => $rma->getReturnToStoreHash(),
                        'store_id'             => $rma->getStoreId(),
                    ];
                }
            }
        }

        $templateOptions = [
            'area' => Area::AREA_FRONTEND,
            'store' => $this->storeManager->getStore()->getStoreId(),
        ];

        try {
            $transport = $this->transportBuilder
                ->setTemplateIdentifier(
                    $this->helper->getConfig('carriers/pickupinstore/order_collected_by_customer_template', $storeId)
                )
                ->setTemplateOptions($templateOptions)
                ->setTemplateVars($templateVars)
                ->setFrom(
                    $this->helper->getConfig('carriers/pickupinstore/sender_email_afer_collect_identity', $storeId)
                )
                ->addTo($order->getCustomerEmail())
                ->getTransport();
            $transport->sendMessage();
        } catch (Exception $exception) {
            $this->logger->error($exception, ['exception' => $exception]);
        } finally {
            $this->inlineTranslation->resume();
        }
    }
}
