<?php

declare(strict_types=1);

namespace FiloBlu\Flow\Model\System;

use FiloBlu\Flow\Helper\Product as Helper;
use Magento\Catalog\Model\Product;
use Magento\Eav\Model\Entity\TypeFactory;
use Magento\Eav\Model\ResourceModel\Entity\Attribute\CollectionFactory;
use Magento\Framework\Data\OptionSourceInterface;

/**
 * Class ProductAttributes
 * @package FiloBlu\Flow\Model\System
 */
class ProductAttributes implements OptionSourceInterface

{
    /**
     * @var TypeFactory
     */
    protected $typeFactory;

    /**
     * @var CollectionFactory
     */
    protected $collectionFactory;

    /**
     * @var Helper
     */
    protected $helper;

    /**
     * ProductAttributes constructor.
     * @param TypeFactory $typeFactory
     * @param CollectionFactory $collectionFactory
     * @param Helper $helper
     */
    public function __construct(
        TypeFactory       $typeFactory,
        CollectionFactory $collectionFactory,
        Helper            $helper
    ) {
        $this->typeFactory = $typeFactory;
        $this->collectionFactory = $collectionFactory;
        $this->helper = $helper;
    }

    /**
     * @return array
     */
    public function toOptionArray()
    {
        $options = [];
        $attributes = $this->getAttributesToCopy();
        $attributeGroups = array_unique($attributes->getColumnValues('attribute_group_name'));
        foreach ($attributeGroups as $attributeGroupName) {
            $groupedOptions = [];
            $groupAttributes = $attributes->getItemsByColumnValue('attribute_group_name', $attributeGroupName);
            foreach ($groupAttributes as $attribute) {
                $attributeLabel = $attribute->getFrontendLabel() ?: $attribute->getAttributeCode();
                $groupedOptions[] = [
                    'label' => $attributeLabel,
                    'value' => $attribute->getAttributeCode()
                ];
            }

            $options[] = [
                'label' => $attributeGroupName,
                'value' => $groupedOptions
            ];
        }

        return $options;
    }

    /**
     * @return mixed
     */
    public function getAttributesToCopy()
    {
        $excludedGroups = [
            'Prices',
            'Recurring Profile'
        ];

        $excludedAttributes = [
            'sku',
            'status',
            'visibility',
            'old_id',
// 			'url_key',
// 			'url_path',
            'has_options',
            'required_options',
            'options_container',
            'created_at',
            'updated_at',
            'category_ids',
            'barcode'
        ];

        $excludedFrontendInputs = [
            'price',
            'image',
            'media_image',
            'gallery',
            'filter_price_range',
            'price',
            'special_price',
            'tier_price',
            'minimal_price',
            'price_type',
            'price_view',
            'msrp_display_actual_price_type',
            'gift_wrapping_price',
            'hide_price'
        ];

        $productEntityType = $this->typeFactory->create()->loadByCode(Product::ENTITY);
        $attributes = $this->collectionFactory->create();
        $attributes->setEntityTypeFilter($productEntityType);
        $attributes->join(['eea' => 'eav_entity_attribute'], 'main_table.attribute_id = eea.attribute_id', ['group_id' => 'eea.attribute_group_id']);
        $attributes->join(['eeg' => 'eav_attribute_group'], 'eea.attribute_group_id = eeg.attribute_group_id', ['attribute_group_name' => 'eeg.attribute_group_name']);
        $attributes->addFieldToFilter('attribute_group_name', ['nin' => $excludedGroups]);
        $attributes->addFieldToFilter('frontend_input', ['nin' => $excludedFrontendInputs]);
        $attributes->addFieldToFilter('attribute_code', ['nin' => $excludedAttributes]);
        $attributes->getSelect()->group('main_table.attribute_id');
        $attributes->getSelect()->order('attribute_group_name ASC');

        return $attributes;
    }

    /**
     * @return array
     */
    public function getFinalAttributesToCopy(): array
    {
        return $this->helper->arrayDiff(
            $this->getAttributesToCopy()->getColumnValues('attribute_code'),
            $this->helper->getSuperAttributesArray()
        );
    }
}
