<?php

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

namespace FiloBlu\Rma\Plugin\Model;

use Exception;
use FiloBlu\Rma\Handlers\CancelChangeSizeOrderHandler;
use FiloBlu\Rma\Handlers\CreateChangeSizeOrderHandler;
use FiloBlu\Rma\Handlers\EasyReturnHandler;
use FiloBlu\Rma\Handlers\RmaEmailHandler;
use FiloBlu\Rma\Handlers\RmaItemStatusUpdateHandler;
use FiloBlu\Rma\Handlers\RmaPoliciesHandler;
use FiloBlu\Rma\Helper\ChangeSizeAttributeHelper;
use FiloBlu\Rma\Helper\ChangeSizeItemsHelper;
use FiloBlu\Rma\Helper\RmaItemResolutionHistoryHelper;
use FiloBlu\Rma\Logger\Logger;
use Magento\Rma\Api\Data\RmaInterface;
use Magento\Rma\Model\Rma;
use Throwable;

/**
 *
 */
class RmaModelRmaProcessor
{
    /**
     * @var RmaPoliciesHandler
     */
    protected $rmaPoliciesHandler;
    /**
     * @var Logger
     */
    private $logger;
    /**
     * @var EasyReturnHandler
     */
    private $easyReturnHandler;
    /**
     * @var RmaItemStatusUpdateHandler
     */
    private $rmaItemStatusUpdateHandler;
    /**
     * @var RmaEmailHandler
     */
    private $rmaEmailHandler;
    /**
     * @var CancelChangeSizeOrderHandler
     */
    private $cancelChangeSizeOrderHandler;
    /**
     * @var CreateChangeSizeOrderHandler
     */
    private $createChangeSizeOrderHandler;
    /**
     * @var RmaItemResolutionHistoryHelper
     */
    private $resolutionHistoryHelper;
    /**
     * @var ChangeSizeItemsHelper
     */
    private $changeSizeItemsHelper;
    /**
     * @var array
     */
    private $rmaItemsChangeSizeValues = [];
    /**
     * @var ChangeSizeAttributeHelper
     */
    private $changeSizeAttributeHelper;

    /**
     * RmaModelRmaProcessor constructor.
     * @param Logger $logger
     * @param EasyReturnHandler $easyReturnHandler
     * @param RmaItemStatusUpdateHandler $rmaItemStatusUpdateHandler
     * @param RmaEmailHandler $rmaEmailHandler
     * @param CancelChangeSizeOrderHandler $cancelChangeSizeOrderHandler
     * @param CreateChangeSizeOrderHandler $createChangeSizeOrderHandler
     * @param RmaPoliciesHandler $rmaPoliciesHandler
     * @param RmaItemResolutionHistoryHelper $resolutionHistoryHelper
     * @param ChangeSizeItemsHelper $changeSizeItemsHelper
     * @param ChangeSizeAttributeHelper $changeSizeAttributeHelper
     */
    public function __construct(
        Logger $logger,
        EasyReturnHandler $easyReturnHandler,
        RmaItemStatusUpdateHandler $rmaItemStatusUpdateHandler,
        RmaEmailHandler $rmaEmailHandler,
        CancelChangeSizeOrderHandler $cancelChangeSizeOrderHandler,
        CreateChangeSizeOrderHandler $createChangeSizeOrderHandler,
        RmaPoliciesHandler $rmaPoliciesHandler,
        RmaItemResolutionHistoryHelper $resolutionHistoryHelper,
        ChangeSizeItemsHelper $changeSizeItemsHelper,
        ChangeSizeAttributeHelper $changeSizeAttributeHelper
    ) {
        $this->logger = $logger;
        $this->easyReturnHandler = $easyReturnHandler;
        $this->rmaItemStatusUpdateHandler = $rmaItemStatusUpdateHandler;
        $this->rmaEmailHandler = $rmaEmailHandler;
        $this->cancelChangeSizeOrderHandler = $cancelChangeSizeOrderHandler;
        $this->createChangeSizeOrderHandler = $createChangeSizeOrderHandler;
        $this->rmaPoliciesHandler = $rmaPoliciesHandler;
        $this->resolutionHistoryHelper = $resolutionHistoryHelper;
        $this->changeSizeItemsHelper = $changeSizeItemsHelper;
        $this->changeSizeAttributeHelper = $changeSizeAttributeHelper;
    }

    /**
     * @param \Magento\Rma\Api\Data\RmaInterface $subject
     * @param $data
     * @return array[]|mixed|null
     */
    public function beforeSaveRma(RmaInterface $subject, $data)
    {
        return $this->cleanChangeSizeAttributeValuesForValidation($subject->getOrderId(), $data);
    }

    /**
     * @param Rma $subject
     * @param \Magento\Rma\Api\Data\RmaInterface|bool $result
     * @return Rma
     * @throws \Exception
     * @throws \Throwable
     */
    public function afterSaveRma(RmaInterface $subject, $result)
    {
        if ($result === false) {
            return $subject;
        }

        if (in_array($subject->getStatus(), ['closed', 'rejected_on_item'])) {
            $this->afterClose($subject, $result);

            if ($result->getData('change_size_orders_count')) {
                return $result;
            }
        }

        try {

            //check if EasyRma is enabled then save EasyRma Fields
            $this->easyReturnHandler->saveEasyReturnFields($subject, $result);

            //Save Rma Item Status History
            $this->resolutionHistoryHelper->saveRmaItemsData($result);

            $this->setChangeSizeAttributeValuesBeforeCreateChangeSizeOrder($subject->getOrderId(), $result);

            //Save Change Size Items Data
            $changeSizeItem = [];
            if ($this->changeSizeItemsHelper->isChangeSizeItemsFeatureEnabled()) {
                $changeSizeItem = $this->changeSizeItemsHelper->saveData($result);
            }

            //generate changeSizeOrder if needed and send new changeSizeOrder email
            $this->createChangeSizeOrderHandler->checkIfCreateChangeSizeOrder($subject, $result, $changeSizeItem);

            //send email for wrong or damaged item
            $this->rmaEmailHandler->sendWrongOrDamagedRmaEmail($result);

            //check if update status to changeSizeOrder or auto approve rma based on BE configuration
            $this->rmaItemStatusUpdateHandler->shouldUpdateStatus($subject, $result);

            //send email if needed
            $this->rmaEmailHandler->sendRmaEmail($result);

            //check rma policies
            $this->rmaPoliciesHandler->checkPolicies($result);

        } catch (Exception $e) {
            $this->logger->critical($e->getMessage(), ['exception' => $e]);
            throw $e;
            //return $result;
        } catch (Throwable $t) {
            $this->logger->critical($t->getMessage(), ['exception' => $t]);
            throw $t;
            //return $result;
        }
        return $result;
    }

    /**
     * @param Rma $subject
     * @param $result
     * @return mixed
     */
    public function afterClose(Rma $subject, $result)
    {
        try {
            //cancel ChangeSizeOrder on rma cancel action
            $this->cancelChangeSizeOrderHandler->cancelChangeSizeOrder($subject, $result);
            //send email if needed

            if (!$result->getData('change_size_orders_count')) {
                return $result;
            }

            $this->rmaEmailHandler->sendRmaEmail($result);
            return $result;
        } catch (Exception $e) {
            $this->logger->critical($e->getMessage(), ['exception' => $e]);
            return $result;
        } catch (Throwable $t) {
            $this->logger->critical($t->getMessage(), ['exception' => $t]);
            return $result;
        }
    }

    /**
     * This method sets the value of the change_size attribute to null since the M2.4.7
     * version is very restrictive on attribute validation and does not allow select
     * or dropdown attributes without options
     *
     * @param $orderId
     * @param $data
     * @return mixed
     */
    public function cleanChangeSizeAttributeValuesForValidation($orderId, $data)
    {
        if (empty($data)) {
            return null;
        }

        $itemsChanged = 0;

        foreach ($data['items'] as $key => $item) {
            if (!empty($item['change_size'])) {
                $this->rmaItemsChangeSizeValues[$orderId][$item['order_item_id']] = $item['change_size'];
                unset($data['items'][$key]['change_size']);
                $itemsChanged++;
            }
        }

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

        return [$data];
    }

    /**
     * This method sets the value of the change_size attribute to its original value
     * in order to allow correct change size order creation
     *
     * @param $orderId
     * @param $result
     */
    public function setChangeSizeAttributeValuesBeforeCreateChangeSizeOrder($orderId, $result)
    {
        if (!empty($this->rmaItemsChangeSizeValues)) {
            foreach ($result->getItems() as $key => $item) {

                $orderItemId = $item->getOrderItemId();

                if (empty($this->rmaItemsChangeSizeValues[$orderId][$orderItemId])) {
                    continue;
                }

                $changeSizeProductId = (int)$this->rmaItemsChangeSizeValues[$orderId][$orderItemId];

                $itemExtensionAttributes = $item->getExtensionAttributes();
                $itemExtensionAttributes->setChangeSize($changeSizeProductId);

                $item->setExtensionAttributes($itemExtensionAttributes);
            }

            unset($this->rmaItemsChangeSizeValues[$orderId]);
        }
    }
}
