<?php
/**
 * Created by PhpStorm.
 * User: jderosa
 * Date: 30/10/19
 * Time: 20.03
 */

namespace FiloBlu\Rma\Setup;

use Exception;
use FiloBlu\Rma\Helper\ChangeSizeAttributeHelper;
use FiloBlu\Rma\Helper\InstallHelper;
use FiloBlu\Rma\Helper\RmaHelper;
use Magento\Cms\Model\BlockFactory;
use Magento\Config\Model\ResourceModel\Config;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\App\Area;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\App\ResourceConnection;
use Magento\Framework\App\State;
use Magento\Framework\Serialize\SerializerInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\UpgradeDataInterface;
use Magento\Store\Api\Data\StoreInterface;
use Magento\Store\Api\StoreRepositoryInterface;
use Magento\Store\Model\ScopeInterface;
use Symfony\Component\Console\Output\ConsoleOutput as Output;
use Throwable;

/**
 *
 */
class UpgradeData implements UpgradeDataInterface
{
    const CMS_BLOCK_IDENTIFIER = 'rma_logistic_warning';
    private static $contents =
        [
            'it'      => '',
            'en'      => '',
            'de'      => '',
            'ja'      => '',
            'ru'      => '',
            'fr'      => '',
            'es'      => '',
            'default' => ''
        ];
    /**
     * @var Output
     */
    protected $output;
    /**
     * @var InstallHelper
     */
    protected $installHelper;
    /**
     * @var BlockFactory
     */
    private $blockFactory;
    /**
     * @var State
     */
    private $state;
    /**
     * @var ResourceConnection
     */
    private $resourceConnection;
    /**
     * @var ScopeConfigInterface
     */
    private $scopeConfig;
    /**
     * @var StoreRepositoryInterface
     */
    private $storeRepositoryInterface;
    /**
     * @var Config
     */
    private $config;
    /**
     * @var ChangeSizeAttributeHelper
     */
    private $changeSizeAttributeHelper;
    /**
     * @var SerializerInterface
     */
    private $serializer;
    /**
     * @var EavSetupFactory
     */
    private $eavSetupFactory;

    /**
     * UpgradeData constructor.
     * @param Output $output
     * @param InstallHelper $installHelper
     * @param BlockFactory $blockFactory
     * @param State $state
     * @param ResourceConnection $resourceConnection
     * @param StoreRepositoryInterface $storeRepositoryInterface
     * @param ScopeConfigInterface $scopeConfig
     * @param Config $config
     * @param ChangeSizeAttributeHelper $changeSizeAttributeHelper
     * @param SerializerInterface $serializer
     * @param EavSetupFactory $eavSetupFactory
     */
    public function __construct(
        Output $output,
        InstallHelper $installHelper,
        BlockFactory $blockFactory,
        State $state,
        ResourceConnection $resourceConnection,
        StoreRepositoryInterface $storeRepositoryInterface,
        ScopeConfigInterface $scopeConfig,
        Config $config,
        ChangeSizeAttributeHelper $changeSizeAttributeHelper,
        SerializerInterface $serializer,
        EavSetupFactory $eavSetupFactory
    ) {
        $this->output = $output;
        $this->installHelper = $installHelper;
        $this->blockFactory = $blockFactory;
        $this->state = $state;
        $this->resourceConnection = $resourceConnection;
        $this->scopeConfig = $scopeConfig;
        $this->storeRepositoryInterface = $storeRepositoryInterface;
        $this->config = $config;
        $this->changeSizeAttributeHelper = $changeSizeAttributeHelper;
        $this->serializer = $serializer;
        $this->eavSetupFactory = $eavSetupFactory;
    }

    /**
     * @param ModuleDataSetupInterface $setup
     * @param ModuleContextInterface $context
     */
    public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
        try {
            $setup->startSetup();
            if (version_compare($context->getVersion(), '2.0.1', '<')) {
                $this->installHelper->addNewOrderStatus($setup);
                $this->installHelper->addNewReasonOption($setup);
                $this->installHelper->addNewRmaItem($setup);
                $this->installHelper->hideReasonOther($setup);
                $this->installHelper->sortAttributes($setup);
            }
            if (version_compare($context->getVersion(), '2.2.0', '<')) {
                //install easy return cms block
                if (!$this->checkIfCmsExists(self::CMS_BLOCK_IDENTIFIER)) {
                    //build unique cms block grouped by locale

                    $this->state->emulateAreaCode(Area::AREA_ADMINHTML, function () {
                        $groupedCmsBlock = $this->buildCmsBlocksUsingLocale();
                        foreach ($groupedCmsBlock as $locale => $cms) {
                            $cmsBlock = $this->blockFactory->create();
                            $cmsBlockData =
                                [
                                    'title'      => 'RMA warnings for language ' . $locale,
                                    'identifier' => self::CMS_BLOCK_IDENTIFIER,
                                    'stores'     => explode(',', $cms),
                                    'content'    => $this->getContentByLocale($locale)

                                ];
                            $cmsBlock->setData($cmsBlockData);
                            $cmsBlock->save();
                        }
                    });
                }
            }
            //install Be standard reason options
            if (version_compare($context->getVersion(), '2.2.1', '<=')) {
                $this->installHelper->createBeReturnReasons($setup);
            }

            if (version_compare($context->getVersion(), '2.2.2', '<=')) {
                $block1Identifier = 'returns-information';
                $block2Identifier = 'easy-return-information';
                $block3Identifier = 'normal-return-information';

                try {
                    $this->state->setAreaCode(Area::AREA_ADMINHTML);

                    if (!$this->checkIfCmsExists($block1Identifier)) {
                        $cmsBlockData = [
                            'content'    => 'Returns information',
                            'identifier' => $block1Identifier,
                            'is_active'  => 1,
                            'stores'     => [0],
                            'title'      => 'Returns Information'
                        ];

                        $this->blockFactory->create()->setData($cmsBlockData)->save();
                    }

                    if (!$this->checkIfCmsExists($block2Identifier)) {
                        $cmsBlockData = [
                            'content'    => 'Easy return information',
                            'identifier' => $block2Identifier,
                            'is_active'  => 1,
                            'stores'     => [0],
                            'title'      => 'Easy Return Information'
                        ];

                        $this->blockFactory->create()->setData($cmsBlockData)->save();
                    }

                    if (!$this->checkIfCmsExists($block3Identifier)) {
                        $cmsBlockData = [
                            'content'    => 'Normal return information',
                            'identifier' => $block3Identifier,
                            'is_active'  => 1,
                            'stores'     => [0],
                            'title'      => 'Normal Return Information'
                        ];

                        $this->blockFactory->create()->setData($cmsBlockData)->save();
                    }
                } catch (Exception $_e) {
                }
            }

            if (version_compare($context->getVersion(), '2.2.3', '<=')) {
                $block1Identifier = 'returning-items-information';
                $block2Identifier = 'easy-return-before-submit-information';

                try {
                    $this->state->setAreaCode(Area::AREA_ADMINHTML);

                    if (!$this->checkIfCmsExists($block1Identifier)) {
                        $cmsBlockData = [
                            'content'    => 'Returning items information',
                            'identifier' => $block1Identifier,
                            'is_active'  => 1,
                            'stores'     => [0],
                            'title'      => 'Returning Items Information'
                        ];

                        $this->blockFactory->create()->setData($cmsBlockData)->save();
                    }

                    if (!$this->checkIfCmsExists($block2Identifier)) {
                        $cmsBlockData = [
                            'content'    => 'Easy-return before-submit information',
                            'identifier' => $block2Identifier,
                            'is_active'  => 1,
                            'stores'     => [0],
                            'title'      => 'Easy-Return Before-Submit Information'
                        ];

                        $this->blockFactory->create()->setData($cmsBlockData)->save();
                    }
                } catch (Exception $_e) {
                }
            }

            if (version_compare($context->getVersion(), '2.2.6', '<=')) {
                $id = "_" . time() . "_" . date("s");

                $value = [
                    $id => [
                        'rma_resolution' => (string)$this->changeSizeAttributeHelper->getChangeSizeAttributeOptionId(),
                        'netsuite_id' => "13"
                    ]
                ];

                // Save configuration
                $this->config->saveConfig(
                    RmaHelper::XML_PATH_RMA_RESOLUTION_MAPPING,
                    $this->serializer->serialize($value),
                    'default',
                    0
                );
            }

            if (version_compare($context->getVersion(), '2.2.8', '<=')) {
                $this->installHelper->addWaitingFormRmaReceivingStatus($setup);
            }

            if (version_compare($context->getVersion(), '2.2.10', '<=')) {
                $this->addIbanForReturnToRmaItem($setup);
            }

            $setup->endSetup();
        } catch (Exception $e) {
            $this->output->writeln('Error while creating new order status : ' . $e->getMessage());
            $setup->endSetup();
        } catch (Throwable $t) {
            $this->output->writeln('Error while creating new order status : ' . $t->getMessage());
            $setup->endSetup();
        }
    }

    /**
     * @param $identifier
     * @return bool
     */
    private function checkIfCmsExists($identifier)
    {
        $connection = $this->resourceConnection->getConnection();
        $table = $connection->getTableName('cms_block');
        $row = $connection->fetchRow("SELECT * FROM $table WHERE identifier = :identifier", ['identifier' => $identifier]);
        if ($row) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * @return array
     */
    private function buildCmsBlocksUsingLocale()
    {
        $allStores = $this->getAllStoreViews();
        $cmsBlock = [];
        foreach ($allStores as $store) {
            if ($store->getCode() != 'admin') {
                $locale = $this->getStoreLocaleByStoreId($store->getId());
                if (!isset($cmsBlock[$locale])) {
                    $cmsBlock[$locale] = $store->getId();
                } else {
                    $cmsBlock[$locale] = $cmsBlock[$locale] . ',' . $store->getId();
                }
            }
        }
        return $cmsBlock;
    }

    /**
     * @return StoreInterface[]
     */
    private function getAllStoreViews()
    {
        return $this->storeRepositoryInterface->getList();
    }

    /**
     * @param int $storeId
     * @return mixed
     */
    private function getStoreLocaleByStoreId(int $storeId)
    {
        return $this->scopeConfig->getValue('general/locale/code', ScopeInterface::SCOPE_STORE, $storeId);
    }

    /**
     * @param string $locale
     * @return string
     */
    private function getContentByLocale(string $locale)
    {
        foreach (self::$contents as $k => $content) {
            if (strstr($locale, $k)) {
                return $content;
            }
        }
        return self::$contents['default'];
    }

    private function addIbanForReturnToRmaItem(ModuleDataSetupInterface $setup)
    {
        if (!$setup->tableExists('magento_rma_item_entity')) {
            return;
        }

        $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);

        $eavSetup->addAttribute(
            'rma_item',
            'iban_for_return',
            [
                'type' => 'varchar',
                'label' => 'IBAN for Return',
                'input' => 'text',
                'required' => false,
                'sort_order' => 100,
                'system' => 0,
                'visible' => true,
                'user_defined' => true,
            ]
        );
    }
}
