<?php

/**
 * Created by PhpStorm.
 * User: jderosa
 * Date: 20/04/20
 * Time: 10.45
 */

namespace FiloBlu\Rma\Plugin\Model\Service;

use Exception;
use FiloBlu\Rma\Helper\ChangeSizeOrder;
use FiloBlu\Rma\Logger\Logger;
use FiloBlu\Rma\Model\RmaEmailManagment;
use FiloBlu\Rma\Plugin\Model\RmaModelRmaProcessor;
use Magento\Rma\Api\Data\RmaInterface;
use Magento\Rma\Api\RmaRepositoryInterface;
use Magento\Rma\Model\Grid;
use Magento\Rma\Model\GridFactory;
use Magento\Rma\Model\Item as ItemModel;
use Magento\Rma\Model\ItemFactory as RmaItemModelFactory;
use Magento\Rma\Model\ResourceModel\Grid as GridResourceModel;
use Magento\Rma\Model\ResourceModel\Item;
use Magento\Rma\Model\ResourceModel\Item\CollectionFactory as ItemCollectionFactory;
use Magento\Rma\Model\Rma;
use Magento\Rma\Model\RmaFactory;
use Magento\Sales\Api\OrderRepositoryInterface;
use Throwable;

/**
 *
 */
class RmaManagmentProcessor
{
    /**
     * @var ChangeSizeOrder
     */
    protected $changeSizeOrderHelper;

    /**
     * @var RmaModelRmaProcessor
     */
    private $rmaModelRmaProcessor;
    /**
     * @var RmaFactory
     */
    private $rmaFactory;
    /**
     * @var RmaEmailManagment
     */
    private $rmaEmailManagement;
    /**
     * @var OrderRepositoryInterface
     */
    private $orderRepository;
    /**
     * @var ItemCollectionFactory
     */
    private $itemCollectionFactory;
    /**
     * @var Item
     */
    private $rmaItemResourceModel;
    /**
     * @var RmaItemModelFactory
     */
    private $rmaItemModelFactory;
    /**
     * @var GridFactory
     */
    private $gridFactory;
    /**
     * @var GridResourceModel
     */
    private $gridResourceModel;
    /**
     * @var Logger
     */
    private $logger;

    /**
     * RmaManagementProcessor constructor.
     * @param Logger $logger
     * @param RmaFactory $rmaFactory
     * @param RmaModelRmaProcessor $rmaModelRmaProcessor
     * @param RmaEmailManagment $rmaEmailManagement
     * @param OrderRepositoryInterface $orderRepository
     * @param ItemCollectionFactory $itemCollectionFactory
     * @param Item $rmaItemResourceModel
     * @param RmaItemModelFactory $rmaItemModelFactory
     * @param GridFactory $gridFactory
     * @param GridResourceModel $gridResourceModel
     * @param ChangeSizeOrder $changeSizeOrderHelper
     */
    public function __construct(
        Logger                   $logger,
        RmaFactory               $rmaFactory,
        RmaModelRmaProcessor     $rmaModelRmaProcessor,
        RmaEmailManagment        $rmaEmailManagement,
        OrderRepositoryInterface $orderRepository,
        ItemCollectionFactory    $itemCollectionFactory,
        Item                     $rmaItemResourceModel,
        RmaItemModelFactory      $rmaItemModelFactory,
        GridFactory              $gridFactory,
        GridResourceModel        $gridResourceModel,
        ChangeSizeOrder          $changeSizeOrderHelper
    ) {
        $this->logger = $logger;
        $this->rmaModelRmaProcessor = $rmaModelRmaProcessor;
        $this->rmaFactory = $rmaFactory;
        $this->rmaEmailManagement = $rmaEmailManagement;
        $this->orderRepository = $orderRepository;
        $this->itemCollectionFactory = $itemCollectionFactory;
        $this->rmaItemResourceModel = $rmaItemResourceModel;
        $this->rmaItemModelFactory = $rmaItemModelFactory;
        $this->gridFactory = $gridFactory;
        $this->gridResourceModel = $gridResourceModel;
        $this->changeSizeOrderHelper = $changeSizeOrderHelper;
    }

    /**
     * @param RmaRepositoryInterface $subject
     * @param RmaInterface $result
     * @param RmaInterface $rmaDataObject
     * @return RmaRepositoryInterface
     * @throws Exception
     * @throws Throwable
     */
    public function afterSave(RmaRepositoryInterface $subject, $result, RmaInterface $rmaDataObject)
    {
        if ($result === false) {
            return $subject;
        }

        try {
            /** @var Rma $rma */
            $rma = $this->rmaFactory->create()->load($result->getEntityId());
            //save data to rmaItem (no provided from api call)
            $this->loadRmaItemsData($rma);
            //save data to rmaGrid (no provided from api call)
            $this->enrichRmaGrid($rma);
            //set change_size extension attributes at runtime
            $rmaItems = $rmaDataObject->getItems();

            $itemExt = [];
            foreach ($rmaItems as $item) {
                if ($item->getExtensionAttributes()->getChangeSize()) {
                    $itemEntityId = $item->getEntityId();
                    $itemExt[$itemEntityId] = $item->getExtensionAttributes()->getChangeSize();
                }
            }

            foreach ($result->getItems() as $item) {
                $itemEntityId = $item->getEntityId();

                if (isset($itemExt[$itemEntityId])) {
                    $extensionAttributes = $item->getExtensionAttributes();
                    if (isset($itemExt[$itemEntityId])) {
                        $extensionAttributes->setChangeSize($itemExt[$itemEntityId]);
                        $item->setExtensionAttributes($extensionAttributes);
                    }
                }
            }

            // Save rma extension attributes
            if ($rmaDataObject->getExtensionAttributes()) {
                $result->setExtensionAttributes($rmaDataObject->getExtensionAttributes());
                $rma->setExtensionAttributes($rmaDataObject->getExtensionAttributes());
            }
            if ($result->getStatus() == 'pending') {
                $this->rmaEmailManagement->sendRmaEmail($result->getEntityId(), 'pending');
            }
            $this->rmaModelRmaProcessor->afterSaveRma($rma, $result);
        } catch (Exception $e) {
            $this->logger->critical($e->getMessage(), ['exception' => $e]);
            throw $e;
        } catch (Throwable $t) {
            $this->logger->critical($t->getMessage(), ['exception' => $t]);
            throw $t;
        }
        return $result;
    }

    /**
     * @param Rma $rma
     */
    private function loadRmaItemsData(Rma $rma)
    {
        try {
            foreach ($rma->getItems() as $item) {

                /** @var ItemModel $item */
                $myItem = $this->rmaItemModelFactory->create();

                $myItem->setEntityId($item->getEntityId());

                if (isset($rma->getOrder()->getItems()[$item->getOrderItemId()]->getData('product_options')['attributes_info'])) {
                    $taglia = $rma->getOrder()->getItems()[$item->getOrderItemId()]->getData('product_options')['attributes_info'][0]['value'];
                    $myItem->setData('product_admin_name', $rma->getOrder()->getItems()[$item->getOrderItemId()]->getName() . "($taglia)");
                } else {
                    $myItem->setData('product_admin_name', $rma->getOrder()->getItems()[$item->getOrderItemId()]->getName());
                }

                $myItem->setData('product_name', $rma->getOrder()->getItems()[$item->getOrderItemId()]->getName());
                $myItem->setData('product_sku', $rma->getOrder()->getItems()[$item->getOrderItemId()]->getSku());
                $myItem->setData('product_admin_sku', $rma->getOrder()->getItems()[$item->getOrderItemId()]->getSku());
                $myItem->setData('product_options', json_encode($rma->getOrder()->getItems()[$item->getOrderItemId()]->getData('product_options')));
                $myItem->setData('resolution', $item->getResolution());
                $this->rmaItemResourceModel->save($myItem);
            }
        } catch (Exception $e) {
            $this->logger->critical($e->getMessage(), ['exception' => $e]);
        } catch (Throwable $t) {
            $this->logger->critical($t->getMessage(), ['exception' => $t]);
        }
    }

    /**
     * @param Rma $rma
     */
    private function enrichRmaGrid(Rma $rma)
    {
        try {
            $orderDate = $rma->getOrder()->getCreatedAt();
            $customerName = $rma->getOrder()->getCustomerName();
            /** @var Grid $rmaGrid */
            $rmaGrid = $this->gridFactory->create();
            $rmaGrid->setEntityId($rma->getEntityId());
            $rmaGrid->setData('order_date', $orderDate);
            $rmaGrid->setData('customer_name', $customerName);
            $this->gridResourceModel->save($rmaGrid);
        } catch (Exception $e) {
            $this->logger->critical($e->getMessage(), ['exception' => $e]);
        } catch (Throwable $t) {
            $this->logger->critical($t->getMessage(), ['exception' => $t]);
        }
    }

    public function beforeSave(RmaRepositoryInterface $subject, RmaInterface $rmaDataObject)
    {
        if (!$rmaDataObject->getExtensionAttributes()) {
            return null;
        }

        $iban = $rmaDataObject->getExtensionAttributes()->getIbanForReturn();

        if (empty($iban)) {
            return null;
        }

        foreach ($rmaDataObject->getItems() as $item) {
            $item->setData('iban_for_return', $iban);
        }

        return [$rmaDataObject];
    }
}
