<?php

declare(strict_types=1);

namespace FiloBlu\Refilo\Setup;

use Blackbird\ContentManager\Model\Content;
use FiloBlu\Refilo\Model\Product\Attribute\Backend\RefiloChildrenCategoriesEnabled;
use FiloBlu\Refilo\Model\Product\Attribute\Backend\RefiloSiblingsCategoriesEnabled;
use Magento\Catalog\Model\Category;
use Magento\Catalog\Model\Category\Attribute\Backend\Image;
use Magento\Catalog\Model\Product;
use Magento\Customer\Model\AttributeFactory;
use Magento\Customer\Model\ResourceModel\Attribute as AttributeResource;
use Magento\Customer\Setup\CustomerSetup;
use Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface;
use Magento\Eav\Model\Entity\Attribute\Source\Boolean;
use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\DB\Ddl\Table;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\UpgradeDataInterface;
use Magento\Framework\Validator\ValidateException;
use Zend_Locale;
use Zend_Validate_Exception;
use Magento\Customer\Setup\CustomerSetupFactory;
use Magento\Eav\Model\Entity\Attribute\Backend\Datetime;
use FiloBlu\Refilo\Model\Config\Source\SearchWeight;

/**
 * @class UpgradeData
 * @package FiloBlu\Refilo\Setup
 */
class UpgradeData implements UpgradeDataInterface
{
    /**
     * @var EavSetupFactory
     */
    protected $eavSetupFactory;

    /**
     * @var CustomerSetupFactory
     */
    private $customerSetupFactory;


    /**
     * @var AttributeFactory
     */
    protected $customerAttributeFactory;

    /**
     * @var AttributeResource
     */
    protected $attributeResource;

    /**
     * UpgradeData constructor.
     * @param EavSetupFactory $eavSetup
     * @param CustomerSetupFactory $customerSetupFactory
     * @param AttributeFactory $customerAttributeFactory
     * @param AttributeResource $attributeResource
     */
    public function __construct(
        EavSetupFactory $eavSetup,
        CustomerSetupFactory $customerSetupFactory,
        AttributeFactory $customerAttributeFactory,
        AttributeResource $attributeResource
    ) {
        $this->eavSetupFactory = $eavSetup;
        $this->customerSetupFactory = $customerSetupFactory;
        $this->customerAttributeFactory = $customerAttributeFactory;
        $this->attributeResource = $attributeResource;
    }

    /**
     * @param ModuleDataSetupInterface $setup
     * @param ModuleContextInterface $context
     * @throws \Magento\Framework\Exception\LocalizedException
     * @throws \Zend_Validate_Exception
     */
    public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
        $installer = $setup;

        $installer->getConnection()->startSetup();
        if (version_compare($context->getVersion(), '1.0.1', '<')) {
            $this->upgradeGeoData($installer);
        }

        if (version_compare($context->getVersion(), '1.0.7', '<')) {
            $this->upgradeContentAttribute($installer);
        }

        if (version_compare($context->getVersion(), '1.0.15', '<')) {
            $this->upgradeCategoryAttributes($installer);
        }

        if (version_compare($context->getVersion(), '1.0.17', '<')) {
            $this->upgradeProductRefiloTemplateAttribute($installer);
            $this->upgradeCategoryRefiloTemplateAttribute($installer);
        }

        if (version_compare($context->getVersion(), '1.0.18', '<')) {
            $this->upgradeCategoryMobileImageAttribute($installer);
        }

        if (version_compare($context->getVersion(), '1.0.19', '<')) {
            $this->addDisableShopMissingAttributes($installer);
        }

        if (version_compare($context->getVersion(), '1.0.20', '<')) {
            $this->upgradeCategoryHideFiltersAttribute($installer);
            $this->upgradeCategoryHideSortbyAttribute($installer);
            $this->upgradeCategoryTitleVariantAttribute($installer);
        }

        if (version_compare($context->getVersion(), '1.0.21', '<')) {
            $this->upgradeCategoryHeadingVariantAttribute($installer);
        }

        if (version_compare($context->getVersion(), '1.0.22', '<')) {
            $this->upgradeCategoryIdentifier($installer);
        }

        if (version_compare($context->getVersion(), '1.0.24', '<')) {
            $this->upgradeCategoryViewMode($installer);
        }

        if (version_compare($context->getVersion(), '1.0.25', '<')) {
            $this->addCareofField($installer);
        }

        if (version_compare($context->getVersion(), '1.0.26', '<')) {
            $this->upgradeChildrenCategoriesEnabled($installer);
        }

        if (version_compare($context->getVersion(), '1.0.30', '<')) {
            $this->addEmotionalProductsAttribute($installer);
        }

        if (version_compare($context->getVersion(), '1.0.31', '<')) {
            $this->upgradeCategoryRefiloTemplateAttributeFixer($installer);
        }

        if (version_compare($context->getVersion(), '1.0.32', '<')) {
            $this->addCategorySearchWeightAttribute($installer);
        }

        if (version_compare($context->getVersion(), '1.0.35', '<')) {
            $this->addCategoryAncestorAttribute($installer);
        }

        if (version_compare($context->getVersion(), '1.0.36', '<')) {
            $this->addTagNewInEnabled($installer);
            $this->addNewIndDate($installer);
            $this->addProductLabel2($installer);
        }

        if (version_compare($context->getVersion(), '1.0.37', '<')) {
            $this->addNoteFields($installer);
        }

        if (version_compare($context->getVersion(), '1.0.38', '<')) {
            $this->upgradeNoteFieldToTextarea($installer);
        }

        $installer->getConnection()->endSetup();
    }

    /**
     * @param ModuleDataSetupInterface $installer
     */
    public function upgradeGeoData(ModuleDataSetupInterface $installer)
    {
        $countryContinentTableName = $installer->getTable('filoblu_refilo_country_continent');
        $continentTableName = $installer->getTable('filoblu_refilo_continent');

        $countryContinentData = json_decode(file_get_contents($this->getFilePath('country_continent.json')), true);
        $continentData = json_decode(file_get_contents($this->getFilePath('continent.json')), true);

        foreach ($countryContinentData as $item) {
            $installer->getConnection()->insertOnDuplicate($countryContinentTableName, $item);
        }

        foreach ($continentData as $item) {
            $installer->getConnection()->insertOnDuplicate($continentTableName, $item);
        }
    }

    /**
     * @param $filename
     * @return string
     */
    public function getFilePath($filename)
    {
        return implode(
            DIRECTORY_SEPARATOR,
            [__DIR__, '..', 'Files', $filename]
        );
    }

    /**
     * @param ModuleDataSetupInterface $installer
     */
    public function upgradeCountryTranslations(ModuleDataSetupInterface $installer)
    {
        $translationTable = $installer->getTable('translation');

        $localeList = ['en_US', 'it_IT', 'fr_FR', 'de_DE', 'es_ES', 'zh_CN', 'ru_RU', 'ja_JP'];

        foreach ($localeList as $locale) {
            $list = Zend_Locale::getTranslationList('territory', $locale, 2);
            foreach ($list as $countryCode => $translation) {
                $item = [
                    'string'    => "country_$countryCode",
                    'store_id'  => 0,
                    'translate' => $translation,
                    'locale'    => $locale
                ];
                $installer->getConnection()->insert($translationTable, $item);
            }
        }
    }

    /**
     * @param ModuleDataSetupInterface $installer
     * @throws \Magento\Framework\Exception\LocalizedException
     * @throws \Zend_Validate_Exception
     */
    private function upgradeContentAttribute(ModuleDataSetupInterface $installer)
    {
        $eavSetup = $this->eavSetupFactory->create(['setup' => $installer]);

        if (!$eavSetup->getAttribute(Content::ENTITY, 'content_block_identifier')) {
            $eavSetup->addAttribute(Content::ENTITY, 'content_block_identifier', [
                'type'         => 'varchar',
                'label'        => 'Content Block Identifier',
                'visible'      => true,
                'required'     => false,
                'user_defined' => false,
                'searchable'   => true,
                'filterable'   => true,
                'comparable'   => false,
                'is_global'    => true,
                'global'       => ScopedAttributeInterface::SCOPE_STORE,
            ]);
        }
    }

    /**
     * @param ModuleDataSetupInterface $installer
     * @throws LocalizedException
     * @throws \Zend_Validate_Exception
     */
    private function upgradeCategoryAttributes(ModuleDataSetupInterface $installer)
    {
        $eavSetup = $this->eavSetupFactory->create(['setup' => $installer]);
        if (!$eavSetup->getAttribute(Category::ENTITY, 'refilo_exclude_from_search')) {
            $eavSetup->addAttribute(
                Category::ENTITY,
                'refilo_exclude_from_search',
                [
                    'type'                  => 'int',
                    'label'                 => 'Excluded from search',
                    'input'                 => 'select',
                    'source'                => Boolean::class,
                    'required'              => false,
                    'sort_order'            => 51,
                    'backend'               => Product\Attribute\Backend\Boolean::class,
                    'global'                => ScopedAttributeInterface::SCOPE_STORE,
                    'group'                 => 'General',
                    'visible'               => true,
                    'is_used_in_grid'       => true,
                    'is_visible_in_grid'    => true,
                    'is_filterable_in_grid' => true,
                    'is_searchable_in_grid' => true
                ]
            );
        }
    }

    /**
     * @param ModuleDataSetupInterface $installer
     * @throws \Magento\Framework\Exception\LocalizedException
     * @throws \Zend_Validate_Exception
     */
    private function upgradeProductRefiloTemplateAttribute(ModuleDataSetupInterface $installer)
    {
        $eavSetup = $this->eavSetupFactory->create(['setup' => $installer]);
        if (!$eavSetup->getAttribute(Product::ENTITY, 'refilo_template')) {
            $eavSetup->addAttribute(
                Product::ENTITY,
                'refilo_template',
                [
                    'type'                    => 'text',
                    'backend'                 => '',
                    'frontend'                => '',
                    'label'                   => 'Refilo Template',
                    'input'                   => 'text',
                    'class'                   => '',
                    'source'                  => '',
                    'global'                  => ScopedAttributeInterface::SCOPE_STORE,
                    'visible'                 => true,
                    'required'                => false,
                    'user_defined'            => false,
                    'default'                 => '',
                    'searchable'              => false,
                    'filterable'              => false,
                    'comparable'              => false,
                    'visible_on_front'        => true,
                    'used_in_product_listing' => true,
                    'unique'                  => false,
                    'apply_to'                => ''
                ]
            );
        }
    }

    /**
     * @param ModuleDataSetupInterface $installer
     * @throws \Magento\Framework\Exception\LocalizedException
     * @throws \Zend_Validate_Exception
     */
    private function upgradeCategoryRefiloTemplateAttribute(ModuleDataSetupInterface $installer)
    {
        $eavSetup = $this->eavSetupFactory->create(['setup' => $installer]);
        if (!$eavSetup->getAttribute(Category::ENTITY, 'refilo_template')) {
            $eavSetup->addAttribute(
                Category::ENTITY,
                'refilo_template',
                [
                    'type'         => 'varchar',
                    'label'        => 'Refilo Template',
                    'input'        => 'text',
                    'sort_order'   => 61,
                    'source'       => '',
                    'visible'      => true,
                    'required'     => false,
                    'user_defined' => false,
                    'searchable'   => false,
                    'filterable'   => false,
                    'comparable'   => false,
                    'is_global'    => true,
                    'global'       => ScopedAttributeInterface::SCOPE_STORE,
                    'group'        => 'General',
                    'backend'      => ''
                ]
            );
        }
    }

    /**
     * @param ModuleDataSetupInterface $installer
     * @throws \Magento\Framework\Exception\LocalizedException
     * @throws \Zend_Validate_Exception
     */
    private function upgradeCategoryMobileImageAttribute(ModuleDataSetupInterface $installer)
    {
        $eavSetup = $this->eavSetupFactory->create(['setup' => $installer]);

        if (!$eavSetup->getAttribute(Category::ENTITY, 'mobile_image')) {
            $eavSetup->addAttribute(
                Category::ENTITY,
                'mobile_image',
                [
                    'type'         => 'varchar',
                    'label'        => 'Mobile Image',
                    'input'        => 'image',
                    'backend'      => Image::class,
                    'sort_order'   => 6,
                    'source'       => '',
                    'visible'      => true,
                    'required'     => false,
                    'user_defined' => false,
                    'searchable'   => true,
                    'filterable'   => true,
                    'comparable'   => false,
                    'is_global'    => true,
                    'global'       => ScopedAttributeInterface::SCOPE_STORE,
                    'group'        => 'General Information',
                ]
            );
        }
    }

    /**
     * @param \Magento\Framework\Setup\ModuleDataSetupInterface $setup
     * @return void
     * @throws \Magento\Framework\Exception\LocalizedException
     * @throws \Zend_Validate_Exception
     */
    public function addDisableShopMissingAttributes(ModuleDataSetupInterface $setup)
    {
        /** @var EavSetup $eavSetup */
        $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);

        if (!$eavSetup->getAttribute(Product::ENTITY, 'disable_shop')) {
            $eavSetup->addAttribute(
                Product::ENTITY,
                'disable_shop', /* Custom Attribute Code */
                [
                    'group'                   => 'Product Details',
                    'type'                    => 'int',
                    'backend'                 => '',
                    'frontend'                => '',
                    'label'                   => 'Disable Shop',
                    'input'                   => 'boolean',
                    'class'                   => '',
                    'source'                  => Boolean::class,
                    'global'                  => ScopedAttributeInterface::SCOPE_WEBSITE,
                    'visible'                 => true,
                    'required'                => false,
                    'user_defined'            => false,
                    'default'                 => '0',
                    'searchable'              => false,
                    'filterable'              => false,
                    'comparable'              => false,
                    'visible_on_front'        => false,
                    'used_in_product_listing' => true,
                    'unique'                  => false
                ]
            );
        }
        if (!$eavSetup->getAttribute(Product::ENTITY, 'hide_price')) {
            $eavSetup->addAttribute(
                Product::ENTITY,
                'hide_price',
                [
                    'group'                   => 'Product Details',
                    'type'                    => 'int',
                    'backend'                 => '',
                    'frontend'                => '',
                    'label'                   => 'Hide Price',
                    'input'                   => 'boolean',
                    'class'                   => '',
                    'source'                  => Boolean::class,
                    'global'                  => ScopedAttributeInterface::SCOPE_WEBSITE,
                    'visible'                 => true,
                    'required'                => false,
                    'user_defined'            => false,
                    'default'                 => '0',
                    'searchable'              => false,
                    'filterable'              => false,
                    'comparable'              => false,
                    'visible_on_front'        => false,
                    'used_in_product_listing' => true,
                    'unique'                  => false
                ]
            );
        }
    }

    /**
     * @param ModuleDataSetupInterface $installer
     * @return void
     * @throws LocalizedException
     * @throws \Zend_Validate_Exception
     */
    private function upgradeCategoryHideFiltersAttribute(ModuleDataSetupInterface $installer)
    {
        $eavSetup = $this->eavSetupFactory->create(['setup' => $installer]);
        if (!$eavSetup->getAttribute(Category::ENTITY, 'refilo_hide_filters')) {
            $eavSetup->addAttribute(
                Category::ENTITY,
                'refilo_hide_filters',
                [
                    'type'                  => 'int',
                    'label'                 => 'Hide Filters',
                    'input'                 => 'select',
                    'source'                => Boolean::class,
                    'required'              => false,
                    'sort_order'            => 70,
                    'backend'               => Product\Attribute\Backend\Boolean::class,
                    'global'                => ScopedAttributeInterface::SCOPE_STORE,
                    'group'                 => 'General',
                    'visible'               => true,
                    'is_used_in_grid'       => true,
                    'is_visible_in_grid'    => true,
                    'is_filterable_in_grid' => true,
                    'is_searchable_in_grid' => true,
                    'default'               => '0'
                ]
            );
        }
    }

    /**
     * @param ModuleDataSetupInterface $installer
     * @return void
     * @throws LocalizedException
     * @throws \Zend_Validate_Exception
     */
    private function upgradeCategoryHideSortbyAttribute(ModuleDataSetupInterface $installer)
    {
        $eavSetup = $this->eavSetupFactory->create(['setup' => $installer]);
        if (!$eavSetup->getAttribute(Category::ENTITY, 'refilo_hide_sortby')) {
            $eavSetup->addAttribute(
                Category::ENTITY,
                'refilo_hide_sortby',
                [
                    'type'                  => 'int',
                    'label'                 => 'Hide Sortby',
                    'input'                 => 'select',
                    'source'                => Boolean::class,
                    'required'              => false,
                    'sort_order'            => 71,
                    'backend'               => Product\Attribute\Backend\Boolean::class,
                    'global'                => ScopedAttributeInterface::SCOPE_STORE,
                    'group'                 => 'General',
                    'visible'               => true,
                    'is_used_in_grid'       => true,
                    'is_visible_in_grid'    => true,
                    'is_filterable_in_grid' => true,
                    'is_searchable_in_grid' => true,
                    'default'               => '0'
                ]
            );
        }
    }

    /**
     * @param ModuleDataSetupInterface $installer
     * @throws LocalizedException
     * @throws \Zend_Validate_Exception
     */
    private function upgradeCategoryTitleVariantAttribute(ModuleDataSetupInterface $installer)
    {
        $eavSetup = $this->eavSetupFactory->create(['setup' => $installer]);
        if (!$eavSetup->getAttribute(Category::ENTITY, 'refilo_tile_variant')) {
            $eavSetup->addAttribute(
                Category::ENTITY,
                'refilo_tile_variant',
                [
                    'type'         => 'varchar',
                    'label'        => 'Tile Variant',
                    'input'        => 'text',
                    'sort_order'   => 72,
                    'source'       => '',
                    'visible'      => true,
                    'required'     => false,
                    'user_defined' => false,
                    'searchable'   => false,
                    'filterable'   => false,
                    'comparable'   => false,
                    'is_global'    => true,
                    'global'       => ScopedAttributeInterface::SCOPE_STORE,
                    'group'        => 'General',
                    'backend'      => ''
                ]
            );
        }
    }

    /**
     * @param \Magento\Framework\Setup\ModuleDataSetupInterface $installer
     * @return void
     * @throws \Magento\Framework\Exception\LocalizedException
     * @throws \Zend_Validate_Exception
     */
    private function upgradeCategoryHeadingVariantAttribute(ModuleDataSetupInterface $installer)
    {
        $eavSetup = $this->eavSetupFactory->create(['setup' => $installer]);
        if (!$eavSetup->getAttribute(Category::ENTITY, 'refilo_heading_variant')) {
            $eavSetup->addAttribute(
                Category::ENTITY,
                'refilo_heading_variant',
                [
                    'type'         => 'varchar',
                    'label'        => 'Header Variant',
                    'input'        => 'text',
                    'sort_order'   => 75,
                    'source'       => '',
                    'visible'      => true,
                    'required'     => false,
                    'user_defined' => false,
                    'searchable'   => false,
                    'filterable'   => false,
                    'comparable'   => false,
                    'is_global'    => true,
                    'global'       => ScopedAttributeInterface::SCOPE_STORE,
                    'group'        => 'General',
                    'backend'      => ''
                ]
            );
        }
    }

    /**
     * @throws Zend_Validate_Exception
     * @throws LocalizedException
     */
    private function upgradeCategoryIdentifier(ModuleDataSetupInterface $installer)
    {
        $eavSetup = $this->eavSetupFactory->create(['setup' => $installer]);
        if (!$eavSetup->getAttribute(Category::ENTITY, 'refilo_category_identifier')) {
            $eavSetup->addAttribute(
                Category::ENTITY,
                'refilo_category_identifier',
                [
                    'type'         => 'varchar',
                    'label'        => 'Refilo Category Identifier',
                    'input'        => 'text',
                    'sort_order'   => 76,
                    'source'       => '',
                    'visible'      => true,
                    'required'     => false,
                    'user_defined' => false,
                    'searchable'   => false,
                    'filterable'   => false,
                    'comparable'   => false,
                    'is_global'    => false,
                    'global'       => ScopedAttributeInterface::SCOPE_STORE,
                    'group'        => 'General',
                    'backend'      => ''
                ]
            );
        }
    }

    private function upgradeCategoryViewMode(ModuleDataSetupInterface $installer)
    {
        $eavSetup = $this->eavSetupFactory->create(['setup' => $installer]);
        if (!$eavSetup->getAttribute(Category::ENTITY, 'refilo_view_mode_enabled')) {
            $eavSetup->addAttribute(
                Category::ENTITY,
                'refilo_view_mode_enabled',
                [
                    'type'                  => 'int',
                    'label'                 => 'View Mode Enabled',
                    'input'                 => 'select',
                    'source'                => Boolean::class,
                    'required'              => false,
                    'sort_order'            => 76,
                    'backend'               => Product\Attribute\Backend\Boolean::class,
                    'global'                => ScopedAttributeInterface::SCOPE_STORE,
                    'group'                 => 'General',
                    'visible'               => true,
                    'is_used_in_grid'       => true,
                    'is_visible_in_grid'    => true,
                    'is_filterable_in_grid' => true,
                    'is_searchable_in_grid' => true,
                    'default'               => '0'
                ]
            );
        }
        if (!$eavSetup->getAttribute(Category::ENTITY, 'refilo_view_mode')) {
            $eavSetup->addAttribute(
                Category::ENTITY,
                'refilo_view_mode',
                [
                    'type'         => 'varchar',
                    'label'        => 'View Mode',
                    'input'        => 'text',
                    'sort_order'   => 77,
                    'source'       => '',
                    'visible'      => true,
                    'required'     => false,
                    'user_defined' => false,
                    'searchable'   => false,
                    'filterable'   => false,
                    'comparable'   => false,
                    'is_global'    => true,
                    'global'       => ScopedAttributeInterface::SCOPE_STORE,
                    'group'        => 'General',
                    'backend'      => ''
                ]
            );
        }
    }

    /**
     * @throws \Zend_Validate_Exception
     * @throws \Magento\Framework\Exception\LocalizedException
     */
    private function addCareofField(ModuleDataSetupInterface $installer): void
    {
        /** @var CustomerSetup $customerSetup */
        $customerSetup = $this->customerSetupFactory->create(['setup' => $installer]);

        if ($customerSetup->getEavConfig()->getAttribute('customer_address', 'care_of')->getId()) {
            return;
        }

        $customerSetup->addAttribute('customer_address', 'care_of', [
            'label'                 => 'Care of',
            'input'                 => 'text',
            'type'                  => Table::TYPE_TEXT,
            'source'                => '',
            'required'              => false,
            'position'              => 75,
            'visible'               => true,
            'system'                => false,
            'is_used_in_grid'       => true,
            'is_visible_in_grid'    => true,
            'is_filterable_in_grid' => true,
            'is_searchable_in_grid' => true,
            'backend'               => ''
        ]);

        $attribute = $this->customerAttributeFactory->create();
        $this->attributeResource->load($attribute, 'care_of', 'attribute_code');

        if ($attribute->getId()) {
            $attribute->setData(
                'used_in_forms',
                [
                    'adminhtml_customer_address',
                    'adminhtml_customer',
                    'customer_address_edit',
                    'customer_register_address',
                    'customer_address',
                ]
            );

            $this->attributeResource->save($attribute);
        }
    }

    private function upgradeChildrenCategoriesEnabled(ModuleDataSetupInterface $installer)
    {
        $eavSetup = $this->eavSetupFactory->create(['setup' => $installer]);
        if (!$eavSetup->getAttribute(Category::ENTITY, 'refilo_children_categories_enabled')) {
            $eavSetup->addAttribute(
                Category::ENTITY,
                'refilo_children_categories_enabled',
                [
                    'type'                  => 'int',
                    'label'                 => 'Children Categories Enabled',
                    'input'                 => 'select',
                    'source'                => Boolean::class,
                    'required'              => false,
                    'sort_order'            => 76,
                    'backend'               => Product\Attribute\Backend\Boolean::class,
                    'global'                => ScopedAttributeInterface::SCOPE_STORE,
                    'group'                 => 'General',
                    'visible'               => true,
                    'is_used_in_grid'       => true,
                    'is_visible_in_grid'    => true,
                    'is_filterable_in_grid' => true,
                    'is_searchable_in_grid' => true,
                    'default'               => '1'
                ]
            );
        }
        if (!$eavSetup->getAttribute(Category::ENTITY, 'refilo_siblings_categories_enabled')) {
            $eavSetup->addAttribute(
                Category::ENTITY,
                'refilo_siblings_categories_enabled',
                [
                    'type'                  => 'int',
                    'label'                 => 'Siblings Categories Enabled',
                    'input'                 => 'select',
                    'source'                => Boolean::class,
                    'required'              => false,
                    'sort_order'            => 76,
                    'backend'               => Product\Attribute\Backend\Boolean::class,
                    'global'                => ScopedAttributeInterface::SCOPE_STORE,
                    'group'                 => 'General',
                    'visible'               => true,
                    'is_used_in_grid'       => true,
                    'is_visible_in_grid'    => true,
                    'is_filterable_in_grid' => true,
                    'is_searchable_in_grid' => true,
                    'default'               => '1'
                ]
            );
        }
    }

    /**
     * @param ModuleDataSetupInterface $installer
     * @return void
     * @throws LocalizedException
     * @throws Zend_Validate_Exception
     */
    private function addEmotionalProductsAttribute(ModuleDataSetupInterface $installer)
    {
        $eavSetup = $this->eavSetupFactory->create(['setup' => $installer]);
        if (!$eavSetup->getAttribute(Category::ENTITY, 'emotional_products')) {
            $eavSetup->addAttribute(
                Category::ENTITY,
                'emotional_products',
                [
                    'type'         => Table::TYPE_TEXT,
                    'input'        => 'text',
                    'label'        => 'Emotional Products',
                    'sort_order'   => 77,
                    'source'       => '',
                    'visible'      => true,
                    'required'     => false,
                    'user_defined' => false,
                    'searchable'   => false,
                    'filterable'   => false,
                    'comparable'   => false,
                    'is_global'    => true,
                    'global'       => ScopedAttributeInterface::SCOPE_STORE,
                    'group'        => 'General',
                    'backend'      => ''
                ]
            );
        }
    }

    /**
     * @param ModuleDataSetupInterface $installer
     * @return void
     */
    private function upgradeCategoryRefiloTemplateAttributeFixer(ModuleDataSetupInterface $installer)
    {
        $eavSetup = $this->eavSetupFactory->create(['setup' => $installer]);
        if (!$eavSetup->getAttribute(Category::ENTITY, 'refilo_template')) {
            $eavSetup->addAttribute(
                Category::ENTITY,
                'refilo_template',
                [
                    'type'         => 'text',
                    'label'        => 'Refilo Template',
                    'input'        => 'text',
                    'sort_order'   => 61,
                    'source'       => '',
                    'visible'      => true,
                    'required'     => false,
                    'user_defined' => false,
                    'searchable'   => false,
                    'filterable'   => false,
                    'comparable'   => false,
                    'is_global'    => true,
                    'global'       => ScopedAttributeInterface::SCOPE_STORE,
                    'group'        => 'General',
                    'backend'      => ''
                ]
            );
        }
    }

    /**
     * @param ModuleDataSetupInterface $installer
     * @return void
     */
    private function addCategorySearchWeightAttribute(ModuleDataSetupInterface $installer)
    {
        $eavSetup = $this->eavSetupFactory->create(['setup' => $installer]);
        if (!$eavSetup->getAttribute(Category::ENTITY, 'refilo_search_weight')) {
            $eavSetup->addAttribute(
                Category::ENTITY,
                'refilo_search_weight',
                [
                    'type'         => 'int',
                    'label'        => 'Search Weight',
                    'input'        => 'select',
                    'sort_order'   => 78,
                    'source'       => SearchWeight::class,
                    'default'      => 1,
                    'visible'      => true,
                    'required'     => false,
                    'user_defined' => false,
                    'searchable'   => false,
                    'filterable'   => false,
                    'comparable'   => false,
                    'is_global'    => true,
                    'global'       => ScopedAttributeInterface::SCOPE_GLOBAL,
                    'group'        => 'General',
                    'backend'      => ''
                ]
            );
        }
    }

    /**
     * @param ModuleDataSetupInterface $installer
     * @return void
     * @throws LocalizedException
     */
    private function addCategoryAncestorAttribute(ModuleDataSetupInterface $installer)
    {
        $eavSetup = $this->eavSetupFactory->create(['setup' => $installer]);
        if (!$eavSetup->getAttribute(Category::ENTITY, 'refilo_ancestors_categories_enabled')) {
            $eavSetup->addAttribute(
                Category::ENTITY,
                'refilo_ancestors_categories_enabled',
                [
                    'type'                  => 'int',
                    'label'                 => 'Ancestor Categories Enabled',
                    'input'                 => 'select',
                    'source'                => Boolean::class,
                    'required'              => false,
                    'sort_order'            => 100,
                    'backend'               => Product\Attribute\Backend\Boolean::class,
                    'global'                => ScopedAttributeInterface::SCOPE_STORE,
                    'group'                 => 'General',
                    'visible'               => true,
                    'is_used_in_grid'       => true,
                    'is_visible_in_grid'    => true,
                    'is_filterable_in_grid' => true,
                    'is_searchable_in_grid' => true,
                    'default'               => '1'
                ]
            );
        }
    }

    /**
     * @param \Magento\Framework\Setup\ModuleDataSetupInterface $installer
     * @return void
     */
    private function addTagNewInEnabled(ModuleDataSetupInterface $installer)
    {
        $eavSetup = $this->eavSetupFactory->create(['setup' => $installer]);
        if (!$eavSetup->getAttribute(Product::ENTITY, 'tag_new_in_enabled')) {
            $eavSetup->addAttribute(
                Product::ENTITY,
                'tag_new_in_enabled',
                [
                    'group'                   => 'Product Details',
                    'type'                    => 'int',
                    'backend'                 => '',
                    'frontend'                => '',
                    'label'                   => 'Enable Tag New In',
                    'input'                   => 'boolean',
                    'class'                   => '',
                    'source'                  => Boolean::class,
                    'global'                  => ScopedAttributeInterface::SCOPE_WEBSITE,
                    'visible'                 => true,
                    'required'                => false,
                    'user_defined'            => true,
                    'default'                 => '0',
                    'searchable'              => false,
                    'filterable'              => false,
                    'comparable'              => false,
                    'visible_on_front'        => false,
                    'used_in_product_listing' => true,
                    'unique'                  => false
                ]
            );

            $attributeSetIds = $eavSetup->getAllAttributeSetIds(Product::ENTITY);
            foreach ($attributeSetIds as $attributeSetId) {
                $eavSetup->addAttributeToGroup(
                    Product::ENTITY,
                    $attributeSetId,
                    'Product Details',
                    'tag_new_in_enabled',
                    null
                );
            }
        }
    }

    /**
     * @param \Magento\Framework\Setup\ModuleDataSetupInterface $installer
     * @return void
     */
    private function addNewIndDate(ModuleDataSetupInterface $installer): void
    {
        $eavSetup = $this->eavSetupFactory->create(['setup' => $installer]);
        if (!$eavSetup->getAttribute(Product::ENTITY, 'new_in_date')) {
            $eavSetup->addAttribute(
                Product::ENTITY,
                'new_in_date',
                [
                    'group'                   => 'Product Details',
                    'type'                    => 'datetime',
                    'backend'                 => Datetime::class,
                    'frontend'                => '',
                    'label'                   => 'Tag New In Date',
                    'input'                   => 'date',
                    'class'                   => '',
                    'global'                  => ScopedAttributeInterface::SCOPE_WEBSITE,
                    'visible'                 => true,
                    'required'                => false,
                    'user_defined'            => true,
                    'default'                 => null,
                    'searchable'              => false,
                    'filterable'              => false,
                    'comparable'              => false,
                    'visible_on_front'        => false,
                    'used_in_product_listing' => true,
                    'unique'                  => false
                ]
            );

            $attributeSetIds = $eavSetup->getAllAttributeSetIds(Product::ENTITY);
            foreach ($attributeSetIds as $attributeSetId) {
                $eavSetup->addAttributeToGroup(
                    Product::ENTITY,
                    $attributeSetId,
                    'Product Details',
                    'new_in_date',
                    null
                );
            }
        }
    }

    /**
     * @throws \Zend_Validate_Exception
     * @throws \Magento\Framework\Exception\LocalizedException
     */
    private function addNoteFields(ModuleDataSetupInterface $installer): void
    {
        $customerSetup = $this->customerSetupFactory->create(['setup' => $installer]);

        if ($customerSetup->getEavConfig()->getAttribute('customer_address', 'note')->getId()) {
            return;
        }

        $customerSetup->addAttribute('customer_address', 'note', [
            'label'                 => 'Note',
            'input'                 => 'textarea',
            'type'                  => Table::TYPE_TEXT,
            'source'                => '',
            'required'              => false,
            'position'              => 76,
            'visible'               => true,
            'system'                => false,
            'is_used_in_grid'       => true,
            'is_visible_in_grid'    => true,
            'is_filterable_in_grid' => true,
            'is_searchable_in_grid' => true,
            'backend'               => '',
            'length'                => 255
        ]);

        $attribute = $this->customerAttributeFactory->create();
        $this->attributeResource->load($attribute, 'note', 'attribute_code');

        if ($attribute->getId()) {
            $attribute->setData(
                'used_in_forms',
                [
                    'adminhtml_customer_address',
                    'adminhtml_customer',
                    'customer_address_edit',
                    'customer_register_address',
                    'customer_address',
                ]
            );

            $this->attributeResource->save($attribute);
        }
    }

    /**
     * Render the note attribute as a textarea in the backend forms and extend its length to 255 chars.
     *
     * @param ModuleDataSetupInterface $installer
     * @throws \Magento\Framework\Exception\LocalizedException
     */
    private function upgradeNoteFieldToTextarea(ModuleDataSetupInterface $installer)
    {
        /** @var CustomerSetup $customerSetup */
        $customerSetup = $this->customerSetupFactory->create(['setup' => $installer]);

        $attribute = $customerSetup->getEavConfig()->getAttribute('customer_address', 'note');
        if (!$attribute->getId()) {
            return;
        }

        $customerSetup->updateAttribute('customer_address', 'note', 'frontend_input', 'textarea');
        $customerSetup->updateAttribute('customer_address', 'note', 'frontend_class', 'validate-length maximum-length-255');
    }

    /**
     * @param \Magento\Framework\Setup\ModuleDataSetupInterface $installer
     * @return void
     */
    private function addProductLabel2(ModuleDataSetupInterface $installer): void
    {
        $eavSetup = $this->eavSetupFactory->create(['setup' => $installer]);
        if (!$eavSetup->getAttribute(Product::ENTITY, 'product_label2')) {
            $eavSetup->addAttribute(
                Product::ENTITY,
                'product_label2',
                [
                    'group'                   => 'Product Details',
                    'type'                    => 'varchar',
                    'backend'                 => '',
                    'frontend'                => '',
                    'label'                   => 'Product Label 2',
                    'input'                   => 'text',
                    'class'                   => '',
                    'source'                  => '',
                    'global'                  => ScopedAttributeInterface::SCOPE_WEBSITE,
                    'visible'                 => true,
                    'required'                => false,
                    'user_defined'            => true,
                    'default'                 => null,
                    'searchable'              => false,
                    'filterable'              => false,
                    'comparable'              => false,
                    'visible_on_front'        => false,
                    'used_in_product_listing' => true,
                    'unique'                  => false
                ]
            );

            $attributeSetIds = $eavSetup->getAllAttributeSetIds(Product::ENTITY);
            foreach ($attributeSetIds as $attributeSetId) {
                $eavSetup->addAttributeToGroup(
                    Product::ENTITY,
                    $attributeSetId,
                    'Product Details',
                    'product_label2',
                    null
                );
            }
        }
    }
}
