<?php

namespace FiloBlu\Rma\Console;

use FiloBlu\Rma\Api\Data\ChangeSizeItemsInterface;
use FiloBlu\Rma\Model\ChangeSizeItems;
use FiloBlu\Rma\Model\ChangeSizeItemsFactory;
use FiloBlu\Rma\Model\ResourceModel\ChangeSizeItems\Collection;
use FiloBlu\Rma\Model\ResourceModel\ChangeSizeItems\CollectionFactory;
use FiloBlu\Rma\Model\Rma\RmaExtensionAttributesRepository;
use Magento\Catalog\Model\ProductRepository;
use Magento\Framework\App\ObjectManager;
use Magento\Framework\App\ResourceConnection;
use Magento\Framework\App\State;
use Magento\Framework\DataObject;
use Magento\Rma\Api\Data\RmaInterface;
use Magento\Rma\Model\Item;
use Magento\Rma\Model\RmaFactory;
use Magento\Sales\Model\OrderFactory;
use Magento\Sales\Model\OrderRepository;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;


/**
 *
 */
class GenerateMissingChangeSizeOrders extends Command
{
    /**
     * @var ResourceConnection
     */
    protected $resourceConnection;
    /**
     * @var RmaFactory
     */
    protected $rmaFactory;
    /**
     * @var OrderFactory
     */
    protected $orderFactory;
    /**
     * @var ObjectManager
     */
    protected $objectManager;
    /**
     * @var \FiloBlu\Rma\Helper\ChangeSizeItemsHelper|mixed
     */
    protected $changeSizeItemsHelper;
    /**
     * @var State
     */
    private $state;
    /**
     * @var ChangeSizeItemsFactory
     */
    private $changeSizeItemsFactory;
    /**
     * @var RmaExtensionAttributesRepository
     */
    private $rmaExtensionAttributesRepository;
    /**
     * @var ProductRepository
     */
    private $productRepository;
    /**
     * @var OrderRepository
     */
    private $orderRepository;
    /**
     * @var CollectionFactory
     */
    private $changeSizeItemsCollectionFactory;

    /**
     * @param ResourceConnection $resourceConnection
     * @param RmaFactory $rmaFactory
     * @param State $state
     * @param ChangeSizeItemsFactory $changeSizeItemsFactory
     * @param RmaExtensionAttributesRepository $rmaExtensionAttributesRepository
     * @param ProductRepository $productRepository
     * @param OrderRepository $orderRepository
     * @param CollectionFactory $changeSizeItemsCollectionFactory
     * @param string $name
     */
    public function __construct(
        ResourceConnection               $resourceConnection,
        RmaFactory                       $rmaFactory,
        State                            $state,
        ChangeSizeItemsFactory           $changeSizeItemsFactory,
        RmaExtensionAttributesRepository $rmaExtensionAttributesRepository,
        ProductRepository                $productRepository,
        OrderRepository                  $orderRepository,
        CollectionFactory                $changeSizeItemsCollectionFactory,
                                         $name = null
    )
    {
        parent::__construct($name);
        $this->resourceConnection = $resourceConnection;
        $this->rmaFactory = $rmaFactory;
        $this->state = $state;
        $this->changeSizeItemsFactory = $changeSizeItemsFactory;
        $this->rmaExtensionAttributesRepository = $rmaExtensionAttributesRepository;
        $this->productRepository = $productRepository;
        $this->orderRepository = $orderRepository;
        $this->objectManager = ObjectManager::getInstance();
        $this->changeSizeItemsCollectionFactory = $changeSizeItemsCollectionFactory;
    }

    /**
     *
     */
    protected function configure()
    {
        $this->setName('filoblu:rma:generate:missing')
            ->setDescription('ChangeSize order increment ID')
            ->addOption(
                'identifier',
                '-i',
                InputOption::VALUE_REQUIRED | InputArgument::IS_ARRAY,
                'RMA ID or increment ID'
            )
            ->addOption(
                'skus',
                '-s',
                InputOption::VALUE_REQUIRED | InputArgument::IS_ARRAY,
                'New ChangeSize Skus'
            );

        $this->setDescription(
            'Run this code to generate missing Change Size Orders related to RMA items with ChangeSize Resolution'
        );
        parent::configure();
    }

    /**
     * @param InputInterface $input
     * @param OutputInterface $output
     * @return int
     * @throws \Exception
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $this->state->setAreaCode('adminhtml');

        $this->changeSizeItemsHelper = $this->objectManager->get(\FiloBlu\Rma\Helper\ChangeSizeItemsHelper::class);

        $identifiers = explode(',', $input->getOption('identifier'));
        $skus = explode(',', $input->getOption('skus'));
        $connection = $this->resourceConnection->getConnection();

        if (empty($identifiers) || empty($skus)) {
            return 1;
        }

        if ($identifiers) {

            foreach ($identifiers as $identifier) {
                $rmaTable = $connection->getTableName('magento_rma');
                $query = $connection->select()->from($rmaTable, ['entity_id', 'increment_id'])->where('increment_id = ?', $identifier);
                $rmaId = $connection->fetchCol($query);
                $rmaId = (int)array_shift($rmaId);
                $rma = $this->rmaFactory->create()->load($rmaId);

                $count = 0;
                foreach ($rma->getItems() as $item) {

                    $oldSku = $item->getProductSku();
                    $newSku = $skus[$count];

                    /** @var ChangeSizeItems $changeSizeItem */
                    $changeSizeItem = $this->findOrCreateChangeSizeItem($item->getId(), $oldSku, $newSku);

                    if ($changeSizeOrderId = $this->rmaExtensionAttributesRepository->getChangeSizeOrderId($item->getId())) {
                        if (!$this->checkIfChangeSizeOrderExists($changeSizeItem->getChangeSizeOrderId())) {
                            $order = $this->generateOrder($rma, $item, $changeSizeItem);

                            $changeSizeItem->setChangeSizeOrderId($order->getId());
                            $changeSizeItem->setChangeSizeOrderIncrementId($order->getIncrementId());
                            $changeSizeItem->save();

                            $this->rmaExtensionAttributesRepository->setChangeSizeOrderId($item->getId(), $order->getId());
                        }
                        continue;
                    }

                    if (empty($changeSizeItem->getId()))
                    {
                        $changeSizeItem
                            ->setParentOrderId($rma->getOrderId())
                            ->setParentOrderIncrementId($rma->getOrderIncrementId())
                            ->setRmaId($rma->getId())
                            ->setRmaIncrementId($rma->getIncrementId())
                            ->setParentOrderItem($item->getOrderItemId())
                            ->setParentProductSku($oldSku)
                            ->setNewProductSku($newSku)
                            ->setIsEasyReturn(1)
                            ->setRmaItemId($item->getId())
                            ->save();
                    } else {

                        if (empty($changeSizeOrderId)) {
                            if ($this->checkIfChangeSizeOrderExists($changeSizeItem->getChangeSizeOrderId())) {
                                $this->rmaExtensionAttributesRepository->setChangeSizeOrderId($item->getId(), $changeSizeItem->getChangeSizeOrderId());
                            }
                        }
                    }


                    try {

                        $order = $this->generateOrder($rma, $item, $changeSizeItem);

                        $changeSizeItem->setChangeSizeOrderId($order->getId());
                        $changeSizeItem->setChangeSizeOrderIncrementId($order->getIncrementId());
                        $changeSizeItem->save();
                    } catch (\Exception $e) {
                        $x = null;
                    }

                    $count++;

                }
            }

            return 0;
        }

        return 0;
    }

    /**
     * @param RmaInterface $rma
     * @param Item $rmaItem
     * @param ChangeSizeItemsInterface $changeSizeItem
     * @return bool
     * @throws \Magento\Framework\Exception\InputException
     * @throws \Magento\Framework\Exception\NoSuchEntityException
     */
    public function generateOrder(RmaInterface $rma, Item $rmaItem, ChangeSizeItemsInterface $changeSizeItem)
    {
        $newProduct = $this->productRepository->get($changeSizeItem->getNewProductSku());

        $data = new DataObject([
            'order' => $this->orderRepository->get($changeSizeItem->getParentOrderId()),
            'rma_item' => $rmaItem,
            'product_id' => $rmaItem->getChangeSize() ?: $newProduct->getId(),
            'parent_sku' => $changeSizeItem->getParentProductSku(),
            'rma_entity_id' => $changeSizeItem->getRmaId(),
            'original_order_item_id' => $changeSizeItem->getParentOrderItem(),
            'rma' => $rma
        ]);

        return $this->changeSizeItemsHelper->generateOrder($data);
    }


    public function findOrCreateChangeSizeItem($rmaItemId, $oldSku, $newSku)
    {
        $changeSizeItemsCollection = $this->changeSizeItemsCollectionFactory->create();
        $changeSizeItemsCollection
            ->addFieldToFilter('rma_item_id', ['eq' => $rmaItemId])
            ->addFieldToFilter('parent_product_sku', ['eq' => $oldSku])
            ->addFieldToFilter('new_product_sku', ['eq' => $newSku]);

        return $changeSizeItemsCollection->count() ? $changeSizeItemsCollection->getFirstItem() : $this->changeSizeItemsFactory->create();

    }

    public function checkIfChangeSizeOrderExists($orderId)
    {
        try {
            $this->orderRepository->get($orderId);
            return true;
        } catch (\Exception $exception) {
            return false;
        }

        return false;
    }
}
