<?php
declare(strict_types=1);

namespace FiloBlu\Refilo\Remote;

use FiloBlu\Refilo\Helper\Profiler;
use FiloBlu\Refilo\Remote\IndexerConfiguration\IndexerConfigurationInterface;
use Magento\Framework\DataObject;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Store\Api\Data\StoreInterface;
use function get_class;

/**
 * Class AbstractStoreBasedIndexer
 * @package FiloBlu\Refilo\Remote
 */
abstract class AbstractStoreBasedIndexer extends AbstractIndexer
{
    /**
     * @param array $ids
     * @return void
     * @throws NoSuchEntityException|LocalizedException
     */
    public function executeAction(array $ids)
    {
        $profilerSection = get_class($this) . '::executeAction';

        Profiler::start($profilerSection);

        // Let a misconfigured indexer fail loudly: swallowing this made mview treat the run as a
        // success and consume the changelog. executeList() logs it with context and rethrows.
        $indexTemplate = $this->getGetRemoteIndexTemplate();

        $configuration = $this->getIndexerConfiguration();
        $previousStore = $this->getStoreManager()->getStore();

        foreach ($this->getStoreManager()->getStores() as $store) {

            if (!$store->getIsActive() || !$this->getIndexerHelper()->hasProjectId($store)) {
                continue;
            }

             Profiler::start( 'process ' . $store->getCode());

            $website = $this->getStoreManager()->getWebsite($store->getWebsiteId());

            $collection = $indexTemplate
                ->withValue('%s', $store->getCode())
                ->withValue('%p', $this->getIndexerHelper()->getProjectId($website))
                ->render();

            $this->getStoreManager()->setCurrentStore($store);

            if ($configuration->getAllowDelete() && $configuration->getDeleteOrder() === IndexerConfigurationInterface::DELETE_ORDER_BEFORE_INDEXER) {
                $this->getConnector()->delete($this->getEntitiesToRemove($ids), $collection);
            }

            $arguments = $this->dataObjectFactory->create([
                'data' => [
                    self::ARGUMENT_COLLECTION => $collection
                ]
            ]);

            $provider = $this->entityProviderFactory->create()
                ->forStore($store)
                ->withIds($ids)
                ->prepare();

            $this->walk($provider, $arguments);

            $provider->release();

            if ($configuration->getAllowDelete() && $configuration->getDeleteOrder() === IndexerConfigurationInterface::DELETE_ORDER_AFTER_INDEXER) {
                $this->getConnector()->delete($this->getEntitiesToRemove($ids), $collection);
            }

            Profiler::stop( 'process ' . $store->getCode());
        }

        if($configuration->getAllowDelete()) {
            $this->getDeletedItemFinder()->clean($ids);
        }

        $this->getStoreManager()->setCurrentStore($previousStore);

        Profiler::stop($profilerSection);
    }

    /**
     * @param StoreInterface $store
     * @return DataObject
     * @throws LocalizedException
     */
    public function prepareConnectorMetadata(StoreInterface $store): DataObject
    {
        $metadata = parent::prepareConnectorMetadata($store);
        $metadata->setData('database', $this->getIndexerHelper()->getProjectId($store));
        return $metadata;
    }


}
