<?php

namespace FiloBlu\Rma\Helper;

use FiloBlu\Rma\Api\RmaExtensionAttributesRepositoryInterface;
use FiloBlu\Rma\Handlers\CreateChangeSizeOrderHandler;
use FiloBlu\Rma\Model\ChangeSizeItemsFactory;
use FiloBlu\Rma\Model\EasyReturnRepository;
use FiloBlu\Rma\Model\ResourceModel\ChangeSizeItems\CollectionFactory;
use FiloBlu\Rma\Model\Rma\RmaExtensionAttributesRepository;
use Magento\Catalog\Model\ProductRepository;
use Magento\Framework\App\Helper\AbstractHelper;
use Magento\Framework\App\Helper\Context;
use Magento\Framework\App\RequestInterface;
use Magento\Framework\App\ResourceConnection;
use Magento\Rma\Model\Rma;
use Magento\Rma\Model\Rma\Source\Status;
use Magento\Sales\Api\OrderRepositoryInterface;

class ChangeSizeItemsHelper extends AbstractHelper
{
    const XML_CONFIG_IS_CHANGE_SIZE_ITEMS_ENABLED = 'filoblu_disablerma_section/change_size_items/enabled';
    const XML_CONFIG_CHANGE_SIZE_ITEMS_RMA_STATUSES = 'filoblu_disablerma_section/change_size_items/rma_status';

    /**
     * @var ChangeSizeItemsFactory
     */
    private $changeSizeItemsFactory;
    /**
     * @var RmaExtensionAttributesRepository
     */
    private $rmaExtensionAttributesRepository;
    /**
     * @var ChangeSizeAttributeHelper
     */
    private $changeSizeAttributeHelper;
    /**
     * @var ProductRepository
     */
    private $productRepository;
    /**
     * @var CollectionFactory
     */
    private $changeSizeItemCollection;
    /**
     * @var CreateChangeSizeOrderHandler
     */
    private $changeSizeOrderHandler;
    /**
     * @var OrderRepositoryInterface
     */
    private $orderRepository;
    /**
     * @var ResourceConnection
     */
    private $resourceConnection;
    /**
     * @var RequestInterface
     */
    private $request;

    /**
     * @param Context $context
     * @param ChangeSizeItemsFactory $changeSizeItemsFactory
     * @param RmaExtensionAttributesRepository $rmaExtensionAttributesRepository
     * @param ChangeSizeAttributeHelper $changeSizeAttributeHelper
     * @param ProductRepository $productRepository
     * @param CollectionFactory $changeSizeItemCollection
     * @param CreateChangeSizeOrderHandler $changeSizeOrderHandler
     * @param OrderRepositoryInterface $orderRepository
     * @param ResourceConnection $resourceConnection
     * @param RequestInterface $request
     */
    public function __construct(
        Context $context,
        ChangeSizeItemsFactory $changeSizeItemsFactory,
        RmaExtensionAttributesRepository $rmaExtensionAttributesRepository,
        ChangeSizeAttributeHelper $changeSizeAttributeHelper,
        ProductRepository $productRepository,
        CollectionFactory $changeSizeItemCollection,
        CreateChangeSizeOrderHandler $changeSizeOrderHandler,
        OrderRepositoryInterface $orderRepository,
        ResourceConnection $resourceConnection,
        RequestInterface $request
    )
    {
        parent::__construct($context);
        $this->changeSizeItemsFactory = $changeSizeItemsFactory;
        $this->rmaExtensionAttributesRepository = $rmaExtensionAttributesRepository;
        $this->changeSizeAttributeHelper = $changeSizeAttributeHelper;
        $this->productRepository = $productRepository;
        $this->changeSizeItemCollection = $changeSizeItemCollection;
        $this->changeSizeOrderHandler = $changeSizeOrderHandler;
        $this->orderRepository = $orderRepository;
        $this->resourceConnection = $resourceConnection;
        $this->request = $request;
    }

    /**
     * @param \Magento\Rma\Model\Rma $rma
     * @return array|null
     * @throws \Exception
     */
    public function saveData(Rma $rma)
    {
        $changeSizeResolution = $this->changeSizeAttributeHelper->getChangeSizeAttributeOptionId();
        $changeSizeItems = [];

        $requestRmaItems = [];

        $rmaItems = $this->request->getParam('items', []);

        if (empty($rmaItems)) {
            $rmaItems = $rma->getItems();
        }

        foreach ( $rmaItems ?? [] as $key => $requestItem) {

            if (is_object($requestItem)) {
                $requestItem = $requestItem->toArray();
            }

            if (!array_key_exists('extension_attributes', (array)$requestItem)) {
                continue;
            }

            if (empty($requestItem['change_size']) && empty($requestItem['extension_attributes']->getChangeSize())) {
                continue;
            }

            $requestRmaItems[$requestItem['order_item_id']] = $requestItem['change_size'] ?? $requestItem['extension_attributes']->getChangeSize();
        }


        if (empty($requestRmaItems)) {
            return [];
        }

        $allowedItemStatus = $this->getChangeSizeItemsAlowedRmaStatuses();
        /** @var \Magento\Rma\Model\Item $item */
        foreach ($rma->getItems() as $item) {

            if (!(in_array($item->getStatus(), $allowedItemStatus))) {
                continue;
            }

            if ((int)$item->getResolution() !== $changeSizeResolution) {
                continue;
            }

            if ($changeSizeOrderId = $this->rmaExtensionAttributesRepository->getChangeSizeOrderId($item->getId())) {

                try {
                    $existingChangeSizeOrder = $this->orderRepository->get($changeSizeOrderId);
                    continue;
                } catch (\Magento\Framework\Exception\NoSuchEntityException $e) {

                }
            }

            $changeProductId = null;

            if ($item->getExtensionAttributes() !== null && $item->getExtensionAttributes()->getChangeSize() != null) {
                $item->setChangeSize($item->getExtensionAttributes()->getChangeSize());
                $changeProductId = $item->getExtensionAttributes()->getChangeSize();
            }

            if (!$changeProductId && $item->getChangeSize() != null) {
                $changeProductId = $item->getChangeSize();
            }

            if (empty($changeProductId)) {
                $orderItemId = $item->getOrderItemId();
                $changeProductId = $requestRmaItems[$orderItemId];
            }

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

            try {
                $newProduct = $this->productRepository->getById($changeProductId);
            } catch (\Exception $e) {
                return null;
            }

            $isEasyReturn = false;

            if ( $rma->getExtensionAttributes()) {
                $isEasyReturn = (int)$rma->getExtensionAttributes()->getEasyReturn();
            }

            if (!$isEasyReturn) {
                $isEasyReturn = $this->request->getParam('return_type') === 'easy-return';
            }

            $changeSizeItem = $this->changeSizeItemsFactory->create();

            $data = [
                'parent_order_id' => $rma->getOrderId(),
                'parent_order_increment_id' => $rma->getOrderIncrementId(),
                'rma_id' => $rma->getId(),
                'rma_increment_id' => $rma->getIncrementId(),
                'parent_order_item' => $item->getOrderItemId(),
                'parent_product_sku' => $item->getProductSku(),
                'new_product_sku' => $newProduct->getSku(),
                'is_easy_return' => $isEasyReturn,
                'rma_item_id' => $item->getId(),
            ];

            if (!$this->rowExists($data)) {
                $changeSizeItem->setData($data);
                $changeSizeItem->save();

                $changeSizeItems[$item->getId()] = $changeSizeItem;
            }
        }

        return $changeSizeItems;
    }

    /**
     * @param $data
     * @return int
     */
    public function rowExists($data)
    {
        /** @var \FiloBlu\Rma\Model\ResourceModel\ChangeSizeItems\Collection $collection */
        $collection = $this->changeSizeItemCollection->create();
        $collection->addFieldToSelect('*')
            ->addFieldToFilter('parent_order_id', $data['parent_order_id'])
            ->addFieldToFilter('rma_id', $data['rma_id'])
            ->addFieldToFilter('parent_order_item', $data['parent_order_item']);

        return $collection->count();
    }

    /**
     * @param $data
     * @return bool
     */
    public function generateOrder($data)
    {
        $changeSizeOrder = $this->changeSizeOrderHandler->generateMissingOrder($data);

        if (!$changeSizeOrder) {
            return false;
        }

        $this->updateFiloBluRmaItem($data->getRmaItem()->getId(), $changeSizeOrder->getId());

        return $changeSizeOrder;
    }

    /**
     * @param $item
     * @return bool
     */
    public function needToGenerateChangeSizeOrder($item)
    {
        if (empty($item['rma_item_id'])) {
            return false;
        }

        $changeSizeOrderId = $this->rmaExtensionAttributesRepository->getChangeSizeOrderId($item['rma_item_id']);

        if (!$this->doesOrderExists($changeSizeOrderId)) {
            return true;
        }

        return false;
    }

    /**
     * @param $rmaItemId
     * @param $orderId
     * @return array
     */
    public function updateFiloBluRmaItem($rmaItemId, $orderId)
    {
        $connection = $this->resourceConnection->getConnection();
        $table = $connection->getTableName(RmaExtensionAttributesRepositoryInterface::TABLE_NAME);
        $query = "UPDATE $table SET `order_id` = {$orderId} WHERE `rma_item_id` = {$rmaItemId}";

        return $connection->query($query) ? [true, 'success'] : [false, 'error'];
    }

    /**
     * @return bool
     */
    public function isChangeSizeItemsFeatureEnabled() {
        return $this->scopeConfig->isSetFlag(self::XML_CONFIG_IS_CHANGE_SIZE_ITEMS_ENABLED);
    }

    /**
     * @return false|string[]
     */
    public function getChangeSizeItemsAlowedRmaStatuses()
    {
        return explode(',', $this->scopeConfig->getValue(self::XML_CONFIG_CHANGE_SIZE_ITEMS_RMA_STATUSES));
    }

    /**
     * @param $oderId
     * @return bool
     */
    public function doesOrderExists($oderId)
    {
        try {
            $this->orderRepository->get($oderId);
        } catch (\Magento\Framework\Exception\NoSuchEntityException $noSuchEntityException) {
            return false;
        } catch (\Exception $exception) {
            return false;
        }

        return true;
    }
}
