<?php

namespace FiloBlu\Storelocator\Setup;

use Exception;
use Magento\Catalog\Model\Product;
use Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface;
use Magento\Framework\DB\Ddl\Table;
use Magento\Framework\Exception\AlreadyExistsException;
use Magento\Framework\Setup\UpgradeDataInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Sales\Model\Order;
use Magento\Sales\Model\Order\Status;
use Magento\Sales\Model\Order\StatusFactory;
use Magento\Sales\Model\ResourceModel\Order\Status as StatusResource;
use Magento\Sales\Model\ResourceModel\Order\StatusFactory as StatusResourceFactory;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Eav\Model\Entity\Attribute\SetFactory as AttributeSetFactory;

/**
 * @class UpgradeData
 * @package FiloBlu\Storelocator\Setup
 */
class UpgradeData implements UpgradeDataInterface
{


    /**
     * Delivered in Store Order-Status code
     */
    const ORDER_STATUS_PROCESSING_CODE = 'delivered_in_store';

    /**
     * Delivered in Store Order-Status label
     */
    const ORDER_STATUS_PROCESSING_LABEL = 'Delivered in Store';

    /**
     * Complete in Store Order-Status code
     */
    const ORDER_STATUS_COMPLETE_CODE = 'complete_in_store';

    /**
     * Complete in Store Order-Status label
     */
    const ORDER_STATUS_COMPLETE_LABEL = 'Complete in Store';

    /**
     * @var StatusFactory
     */
    protected $statusFactory;
    /**
     * @var StatusResourceFactory
     */
    protected $statusResourceFactory;
    /**
     * @var EavSetupFactory
     */
    protected $eavSetupFactory;
    /**
     * @var AttributeSetFactory
     */
    protected $attributeSetFactory;

    /**
     * UpgradeData constructor.
     * @param StatusFactory $statusFactory
     * @param StatusResourceFactory $statusResourceFactory
     * @param EavSetupFactory $eavSetupFactory
     * @param AttributeSetFactory $attributeSetFactory
     */
    public function __construct(
        StatusFactory $statusFactory,
        StatusResourceFactory $statusResourceFactory,
        EavSetupFactory $eavSetupFactory,
        AttributeSetFactory $attributeSetFactory
    ) {
        $this->statusFactory = $statusFactory;
        $this->statusResourceFactory = $statusResourceFactory;
        $this->eavSetupFactory = $eavSetupFactory;
        $this->attributeSetFactory = $attributeSetFactory;
    }

    public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
        $setup->startSetup();

        if (version_compare($context->getVersion(), '1.2.0') < 0) {
            // Quote
            $setup->getConnection()
                ->addColumn(
                    $setup->getTable('quote'),
                    'pickup_in_store_id',
                    [
                        'type'    => Table::TYPE_INTEGER,
                        'comment' => 'PickUp In Store ID'
                    ]
                );
            $setup->getConnection()
                ->addColumn(
                    $setup->getTable('quote'),
                    'pickup_in_store_email',
                    [
                        'type'     => Table::TYPE_TEXT,
                        'length'   => 100,
                        'nullable' => true,
                        'comment'  => 'PickUp In Store Email'
                    ]
                );

            // Order
            $setup->getConnection()
                ->addColumn(
                    $setup->getTable('sales_order'),
                    'pickup_in_store_id',
                    [
                        'type'    => Table::TYPE_INTEGER,
                        'comment' => 'PickUp In Store ID'
                    ]
                );
            $setup->getConnection()
                ->addColumn(
                    $setup->getTable('sales_order'),
                    'pickup_in_store_email',
                    [
                        'type'     => Table::TYPE_TEXT,
                        'length'   => 100,
                        'nullable' => true,
                        'comment'  => 'PickUp In Store Email'
                    ]
                );
        }

        if (version_compare($context->getVersion(), '1.2.2') < 0) {
            $setup->getConnection()
                ->addColumn(
                    $setup->getTable('sales_order'),
                    'pickup_in_store_confirm_date',
                    [
                        'type'     => Table::TYPE_TIMESTAMP,
                        'nullable' => true,
                        'comment'  => 'PickUp In Store Confirm Date'
                    ]
                );
        }

        if (version_compare($context->getVersion(), '1.2.3') < 0) {
            $setup->getConnection()
                ->addColumn(
                    $setup->getTable('sales_order'),
                    'pickup_in_store_hash',
                    [
                        'type'     => Table::TYPE_TEXT,
                        'length'   => 100,
                        'nullable' => true,
                        'comment'  => 'PickUp In Store Hash'
                    ]
                );
        }

        if (version_compare($context->getVersion(), '1.3.0') < 0) {
            $setup->getConnection()
                ->addColumn(
                    $setup->getTable('sales_order'),
                    'pickup_in_store_confirm_received_date',
                    [
                        'type'     => Table::TYPE_TIMESTAMP,
                        'nullable' => true,
                        'comment'  => 'PickUp In Store Confirm Received Date'
                    ]
                );
        }

        $this->addNewOrderProcessingStatus();

        $this->addNewOrderCompleteStatus();

        if (version_compare($context->getVersion(), '3.0.2') < 0) {
            $this->addStoreAvailabilityAttribute($setup);
        }

        if (version_compare($context->getVersion(), '3.0.3') < 0) {
            $this->addMissingStoreCode($setup);
        }

        $setup->endSetup();
    }

    /**
     * Create new order processing status
     *
     * @return void
     *
     * @throws Exception
     */
    protected function addNewOrderProcessingStatus()
    {
        /** @var StatusResource $statusResource */
        $statusResource = $this->statusResourceFactory->create();
        /** @var Status $status */
        $status = $this->statusFactory->create();
        $status->setData([
            'status' => self::ORDER_STATUS_PROCESSING_CODE,
            'label'  => self::ORDER_STATUS_PROCESSING_LABEL,
        ]);

        try {
            $statusResource->save($status);
        } catch (AlreadyExistsException $exception) {
            return;
        }

        $status->assignState(Order::STATE_COMPLETE, false, true);
    }

    /**
     * Create new order processing status
     *
     * @return void
     *
     * @throws Exception
     */
    protected function addNewOrderCompleteStatus()
    {
        /** @var StatusResource $statusResource */
        $statusResource = $this->statusResourceFactory->create();
        /** @var Status $status */
        $status = $this->statusFactory->create();
        $status->setData([
            'status' => self::ORDER_STATUS_COMPLETE_CODE,
            'label'  => self::ORDER_STATUS_COMPLETE_LABEL,
        ]);

        try {
            $statusResource->save($status);
        } catch (AlreadyExistsException $exception) {
            return;
        }

        $status->assignState(Order::STATE_COMPLETE, false, true);
    }

    // https://filoblu.atlassian.net/browse/FRAUPRE-8
    protected function addStoreAvailabilityAttribute($setup)
    {

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

        $attribute_exists = $eavSetup->getAttribute(Product::ENTITY, 'disable_store_availability');

        if (!$attribute_exists) {
            $eavSetup->addAttribute(
                Product::ENTITY,
                'disable_store_availability',
                [
                    'group' => 'General',
                    'type' => 'int',
                    'backend' => '',
                    'frontend' => '',
                    'label' => 'Disable Store Availability',
                    'input' => 'boolean',
                    'class' => '',
                    'source' => 'Magento\Eav\Model\Entity\Attribute\Source\Boolean',
                    'global' => ScopedAttributeInterface::SCOPE_STORE,
                    'visible' => true,
                    'required' => false,
                    'user_defined' => true,
                    'default' => '1',
                    'searchable' => false,
                    'filterable' => true,
                    'comparable' => false,
                    'visible_on_front' => true,
                    'used_in_product_listing' => false,
                    'used_for_promo_rules' => false,
                    'unique' => false
                ]
            );
        }
    }

    private function addMissingStoreCode(ModuleDataSetupInterface $setup)
    {
        // TODO:
        // settare  storecode negli ordini e nel quote
    }
}
