<?php

namespace Autogedal\Labels\Ui\DataProvider\Product\Form\Modifier;

use Autogedal\Labels\Model\ResourceModel\Label\CollectionFactory;
use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Model\Locator\LocatorInterface;
use Magento\Ui\Component\Form\Element\Select;
use Magento\Ui\Component\Form\Field;
use Magento\Ui\Component\Form\Fieldset;

class Labels extends \Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AbstractModifier
{
    private const GROUP = 'autogedal_labels';
    private const DATA_SCOPE = 'autogedal_label_ids';
    private const PREVIOUS_GROUP = 'search-engine-optimization';
    private const SORT_ORDER = 95;

    private $locator;
    private $collectionFactory;

    public function __construct(
        LocatorInterface $locator,
        CollectionFactory $collectionFactory
    ) {
        $this->locator = $locator;
        $this->collectionFactory = $collectionFactory;
    }

    public function modifyMeta(array $meta)
    {
        $meta[self::GROUP] = [
            'arguments' => [
                'data' => [
                    'config' => [
                        'label' => __('Autogedal Labels'),
                        'componentType' => Fieldset::NAME,
                        'dataScope' => '',
                        'collapsible' => true,
                        'sortOrder' => $this->getNextGroupSortOrder(
                            $meta,
                            self::PREVIOUS_GROUP,
                            self::SORT_ORDER
                        ),
                    ],
                ],
            ],
            'children' => [
                self::DATA_SCOPE => $this->getLabelsField(),
            ],
        ];

        return $meta;
    }

    public function modifyData(array $data)
    {
        $product = $this->locator->getProduct();
        $productId = (int)$product->getId();
        if (!$productId) {
            return $data;
        }

        $data[$productId][self::DATA_SCOPE] = $this->getSelectedLabelIds($product);
        $data[$productId][self::DATA_SOURCE_DEFAULT][self::DATA_SCOPE] = $data[$productId][self::DATA_SCOPE];

        return $data;
    }

    private function getLabelsField(): array
    {
        return [
            'arguments' => [
                'data' => [
                    'config' => [
                        'componentType' => Field::NAME,
                        'formElement' => Select::NAME,
                        'dataType' => 'text',
                        'label' => __('Assign labels to this product'),
                        'dataScope' => self::DATA_SCOPE,
                        'source' => self::DATA_SOURCE_DEFAULT,
                        'component' => 'Magento_Ui/js/form/element/ui-select',
                        'elementTmpl' => 'ui/grid/filters/elements/ui-select',
                        'filterOptions' => true,
                        'disableLabel' => true,
                        'multiple' => true,
                        'options' => $this->getOptions(),
                        'sortOrder' => 10,
                    ],
                ],
            ],
        ];
    }

    private function getSelectedLabelIds(ProductInterface $product): array
    {
        $sku = (string)$product->getSku();
        if ($sku === '') {
            return [];
        }

        $selected = [];
        $collection = $this->collectionFactory->create();
        $collection->addFieldToFilter('include_type', ['neq' => 1]);
        $collection->addFieldToFilter('is_active', 1);

        foreach ($collection as $label) {
            $includeSku = array_filter(array_map('trim', explode(',', (string)$label->getData('include_sku'))));
            if (in_array($sku, $includeSku, true)) {
                $selected[] = (string)$label->getId();
            }
        }

        return $selected;
    }

    private function getOptions(): array
    {
        $options = [];
        $collection = $this->collectionFactory->create();
        $collection->addFieldToFilter('include_type', ['neq' => 1]);
        $collection->addFieldToFilter('is_active', 1);
        $collection->setOrder('pos', 'ASC');
        $collection->setOrder('label_id', 'ASC');

        foreach ($collection as $label) {
            $options[] = [
                'label' => sprintf(
                    '%s%s',
                    (string)$label->getData('name'),
                    $label->getData('prod_txt') ? ' - ' . (string)$label->getData('prod_txt') : ''
                ),
                'value' => (string)$label->getId(),
            ];
        }

        return $options;
    }
}
