<?php

namespace FiloBlu\Storelocator\Controller\PickUpInStore;

use Exception;
use FiloBlu\Storelocator\Model\Plugin\Rma\Source\Status;
use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Magento\Framework\App\Area;
use Magento\Framework\App\ResourceConnection;
use Magento\Framework\Controller\Result\JsonFactory;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\Mail\Template\TransportBuilder;
use Magento\Framework\Registry;
use Magento\Framework\Stdlib\DateTime\DateTime;
use Magento\Framework\Translate\Inline\StateInterface;
use Magento\Rma\Helper\Data;
use Magento\Rma\Model\ResourceModel\Rma\CollectionFactory;
use Magento\Rma\Model\Rma;
use Magento\Rma\Model\Rma\Status\HistoryFactory;
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 ConfirmReceivedAction extends Action
{
    /**
     * @var \FiloBlu\Storelocator\Helper\Data
     */
    protected $helper;
    /**
     * @var \Magento\Sales\Api\Data\OrderInterfaceFactory
     */
    protected $orderFactory;

    /**
     * @var \Magento\Framework\Mail\Template\TransportBuilder
     */
    protected $transportBuilder;

    /**
     * @var \Magento\Store\Model\StoreManagerInterface
     */
    protected $storeManager;

    /**
     * @var \Magento\Framework\Translate\Inline\StateInterface
     */
    protected $inlineTranslation;

    /**
     * @var \Magento\Payment\Helper\Data
     */
    protected $paymentHelper;

    /**
     * @var \Magento\Sales\Model\Order\Address\Renderer
     */
    protected $addressRenderer;

    /**
     * @var \Magento\Framework\Registry
     */
    protected $registry;

    /**
     * @var \Magento\Framework\App\ResourceConnection
     */
    protected $resourceConnection;

    /**
     * @var \Magento\Rma\Helper\Data
     */
    protected $rmaHelperData;

    /**
     * @var \Magento\Framework\Controller\Result\JsonFactory
     */
    private $resultJsonFactory;

    /**
     * @var \Magento\Framework\Stdlib\DateTime\DateTime
     */
    private $date;

    /**
     * @var \Magento\Rma\Model\ResourceModel\Rma\CollectionFactory
     */
    private $rmaCollectionFactory;
    /**
     * @var \Magento\Rma\Model\Rma\Status\HistoryFactory
     */
    private $rmaStatusHistoryFactory;

    /**
     * @var \Psr\Log\LoggerInterface
     */
    private $logger;

    /**
     * @param \Magento\Framework\App\Action\Context $context
     * @param \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory
     * @param \FiloBlu\Storelocator\Helper\Data $helper
     * @param \Magento\Sales\Api\Data\OrderInterfaceFactory $orderFactory
     * @param \Magento\Framework\Stdlib\DateTime\DateTime $date
     * @param \Magento\Framework\Mail\Template\TransportBuilder $transportBuilder
     * @param \Magento\Store\Model\StoreManagerInterface $storeManager
     * @param \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation
     * @param \Magento\Payment\Helper\Data $paymentHelper
     * @param \Magento\Sales\Model\Order\Address\Renderer $addressRenderer
     * @param \Magento\Framework\Registry $registry
     * @param \Magento\Framework\App\ResourceConnection $resourceConnection
     * @param \Magento\Rma\Model\Rma\Status\HistoryFactory $rmaStatusHistoryFactory
     * @param \Magento\Rma\Model\ResourceModel\Rma\CollectionFactory $rmaCollectionFactory
     * @param \Magento\Rma\Helper\Data $rmaHelperData
     * @param \Psr\Log\LoggerInterface $logger
     */
    public function __construct(
        Context $context,
        JsonFactory $resultJsonFactory,
        \FiloBlu\Storelocator\Helper\Data $helper,
        OrderInterfaceFactory $orderFactory,
        DateTime $date,
        TransportBuilder $transportBuilder,
        StoreManagerInterface $storeManager,
        StateInterface $inlineTranslation,
        \Magento\Payment\Helper\Data $paymentHelper,
        Renderer $addressRenderer,
        Registry $registry,
        ResourceConnection $resourceConnection,
        HistoryFactory $rmaStatusHistoryFactory,
        CollectionFactory $rmaCollectionFactory,
        Data $rmaHelperData,
        LoggerInterface $logger
    ) {
        parent::__construct($context);
        $this->resultJsonFactory = $resultJsonFactory;
        $this->helper = $helper;
        $this->orderFactory = $orderFactory;
        $this->date = $date;
        $this->transportBuilder = $transportBuilder;
        $this->storeManager = $storeManager;
        $this->inlineTranslation = $inlineTranslation;
        $this->paymentHelper = $paymentHelper;
        $this->addressRenderer = $addressRenderer;
        $this->registry = $registry;
        $this->resourceConnection = $resourceConnection;
        $this->rmaHelperData = $rmaHelperData;
        $this->rmaCollectionFactory = $rmaCollectionFactory;
        $this->rmaStatusHistoryFactory = $rmaStatusHistoryFactory;
        $this->logger = $logger;
    }

    /**
     * @return \Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\Result\Json|\Magento\Framework\Controller\ResultInterface|void
     * @throws \Magento\Framework\Exception\NoSuchEntityException
     */
    public function execute()
    {
        $hash = $this->getRequest()->getParam('hash');
        $storeId = $this->storeManager->getStore()->getId();

        $isPickupInStoreEnabled = $this->helper->getPickupInStoreEnabled($storeId);
        $isReturnInStoreEnabled = $this->helper->getReturnToStoreEnabled($storeId);

        if ((!$isPickupInStoreEnabled && !$isReturnInStoreEnabled) || !$hash) {
            $this->_forward('noRoute');
            return;
        }

        // check if is rma or order request
        $order = $this->getOrder($hash);
        $rma = $this->getRma($hash);

        if ($isReturnInStoreEnabled && $rma && $rma->getStatus() === 'authorized') {

            $order = $rma->getOrder();

            if ($order->getId()) {
                $resultJson = $this->resultJsonFactory->create();
                $resultJson->setData(
                    ['message' => __('You confirmed that the order ') . $order->getIncrementId() . __(' was received.')]
                );
                $this->updateRma($rma);
                $this->updateOrder($order);
                $rma->setStatus(Status::STATE_RECEIVED_IN_STORE)
                    ->setReturnToStoreReceivedDate($this->date->gmtDate())
                    ->setIsUpdate(1)
                    ->save();
                // Send mail to customer to inform that the package is available in store.
                $this->_eventManager->dispatch(
                    'filoblu_storelocator_pickupinstore_confirm_received',
                    ['order' => $order]
                );

                return $resultJson;
            }
        }


            if ($order) {
                $order->setPickupInStoreConfirmReceivedDate($this->date->gmtDate());
                $order->save();
                $resultJson = $this->resultJsonFactory->create();
                $resultJson->setData(
                    ['message' => __('You confirmed that the order ') . $order->getIncrementId() . __(' was received.')]
                );
                $this->updateOrder($order);
                // Send mail to customer to inform that the package is available in store.
                $this->sendMail($order);
                $this->_eventManager->dispatch(
                    'filoblu_storelocator_pickupinstore_confirm_received',
                    ['order' => $order]
                );

                return $resultJson;
            }


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

    /**
     * @param Rma |\Magento\Rma\Api\Data\RmaInterface $rma
     * @return void
     */
    public function updateRma($rma)
    {
        $connection = $this->resourceConnection->getConnection();
        $tableName = $this->resourceConnection->getTableName('magento_rma_item_entity');

        $queryRmaItems = 'SELECT * FROM ' . $tableName . ' WHERE rma_entity_id = ' . $rma->getData('entity_id');
        $result = $connection->fetchAll($queryRmaItems);
        foreach ($result as $item) {
            $item_id = $item['entity_id'];
            $qty_request = $item['qty_requested'];

            if ((int)$qty_request > 0) {
                $approvedReturned = ', qty_approved = ' . $qty_request . ', qty_returned = ' . $qty_request;

                $sql = 'UPDATE ' . $tableName . " SET status = '" . Status::STATE_RECEIVED_IN_STORE . "', 
                qty_authorized = " . $qty_request . $approvedReturned . ' WHERE entity_id = ' . $item_id;

                $connection->query($sql);
            }
        }

        $comment = 'Return In Store - The package was picked up by store';
        /** @var \Magento\Rma\Model\Rma\Status\History $rmaHistory */
        $rmaHistory = $this->rmaStatusHistoryFactory->create();
        $rmaHistory->setRmaEntityId($rma->getId());
        $rmaHistory->setComment($comment);
        $rmaHistory->saveComment($comment, false, true);
    }

    /**
     *  Update Order-status
     */
    public function updateOrder($order)
    {
        $order->setState(Order::STATE_COMPLETE, true)->save();
        $order->setStatus('delivered_in_store')->save();
        $order->addStatusToHistory($order->getStatus(), 'Pick Up In Store - The order arrived in the store');
        $order->save();
    }

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

        if (!$this->helper->getConfig('carriers/pickupinstore/email_to_customer_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->getPaymentHtml($order),
            'store'                    => $order->getStore(),
            'formattedShippingAddress' => $this->getFormattedShippingAddress($order),
            'formattedBillingAddress'  => $this->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/email_to_customer_template', $storeId)
                )
                ->setTemplateOptions($templateOptions)
                ->setTemplateVars($templateVars)
                ->setFrom(
                    $this->helper->getConfig('carriers/pickupinstore/sender_email_to_customer_identity', $storeId)
                )
                ->addTo($order->getCustomerEmail())
                ->getTransport();
            $transport->sendMessage();
        } catch (Exception $exception) {
            $this->logger->error($exception, ['exception' => $exception]);
        } finally {
            $this->inlineTranslation->resume();
        }
    }

    /**
     * @param $order
     * @return string
     * @throws \Magento\Framework\Exception\NoSuchEntityException
     */
    protected function getPaymentHtml($order)
    {
        return $this->paymentHelper->getInfoBlockHtml(
            $order->getPayment(),
            $this->storeManager->getStore()->getId()
        );
    }

    /**
     * @param $order
     * @return string|null
     */
    public function getFormattedShippingAddress($order)
    {
        return $order->getIsVirtual()
            ? null
            : $this->addressRenderer->format($order->getShippingAddress(), 'html');
    }

    /**
     * @param $order
     * @return string|null
     */
    public function getFormattedBillingAddress($order)
    {
        return $this->addressRenderer->format($order->getBillingAddress(), 'html');
    }

    /**
     * @param string|null $hash
     * @return \Magento\Sales\Api\Data\OrderInterface|null
     */
    public function getOrder($hash){

        try
        {
            return $this->helper->getOrderByHash($hash);
        } catch (NoSuchEntityException $e)
        {
            return null;
        }

    }

    /**
     * @param string|null $hash
     * @return Rma|null
     */
    public function getRma($hash){
        try
        {
            /** @var Rma $rma */
            return $this->helper->getRmaByHash($hash);
        } catch (NoSuchEntityException $e)
        {
            return null;
        }
    }
}
