<?php
declare(strict_types=1);

namespace FiloBlu\Refilo\Remote;

use Exception;
use FiloBlu\Refilo\Helper\Profiler;
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 AbstractWebsiteBasedIndexer
 * @package FiloBlu\Refilo\Remote
 */
abstract class AbstractWebsiteBasedIndexer extends AbstractIndexer
{
    /** @var string */
    public const ARGUMENT_WEBSITE = 'website';

    /**
     * @param array $ids
     * @return void
     * @throws \Magento\Framework\Exception\LocalizedException
     */
    public function executeAction(array $ids)
    {
        $profilerSection = get_class($this) . '::executeAction';

        Profiler::start($profilerSection);

        foreach ($this->getStoreManager()->getWebsites() as $website) {

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

            //TODO validate the idea to implement deleter for website based indexers

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

            $provider = $this->entityProviderFactory->create()
                ->forWebsite($website)
                ->withIds($ids)
                ->prepare();

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

            $provider->release();
            Profiler::stop('process ' . $website->getCode());
        }

        Profiler::stop($profilerSection);
    }

    /**
     * @param $entities
     * @param $size
     * @param DataObject $arguments
     * @throws NoSuchEntityException
     * @throws \Magento\Framework\Exception\LocalizedException
     */
    public function onRead($entities, $size, DataObject $arguments)
    {
        $website = $arguments->getData(self::ARGUMENT_WEBSITE);
        $previousStore = $this->getStoreManager()->getStore();

        try {
            $indexTemplate = $this->getGetRemoteIndexTemplate();
        } catch (Exception $exception) {
            $this->logger->error($exception->getMessage(), ['exception' => $exception]);
            return;
        }

        /** @var StoreInterface $store */
        foreach ($website->getStores() as $store) {
            $this->getStoreManager()->setCurrentStore($store);

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

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

            parent::onRead($entities, $size, $this->dataObjectFactory->create([
                'data' => [
                    self::ARGUMENT_COLLECTION => $collection
                ]
            ]));

        }

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

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