<?php
declare(strict_types=1);

namespace FiloBlu\Refilo\Model\Deleter;

use FiloBlu\Refilo\Remote\AbstractIndexer;
use FiloBlu\Refilo\Remote\IndexerConfiguration\IndexerResolver;
use Magento\Framework\App\ObjectManager;
use Magento\Framework\Exception\LocalizedException;
use Magento\Store\Model\StoreManagerInterface;

class ItemCleaner
{
    /**
     * @var IndexerResolver
     */
    private $indexerResolver;
    /**
     * @var StoreManagerInterface
     */
    private $storeManager;

    /**
     * @param IndexerResolver $indexerResolver
     * @param StoreManagerInterface $storeManager
     */
    public function __construct(
        IndexerResolver       $indexerResolver,
        StoreManagerInterface $storeManager
    )
    {
        $this->indexerResolver = $indexerResolver;
        $this->storeManager = $storeManager;
    }

    /**
     * Cleans deleted items for all configured indexers.
     *
     * Iterates through each indexer resolved by the IndexerResolver,
     * checks if the action class is a valid AbstractIndexer,
     * creates an instance, and calls cleanByIndexer for each.
     *
     * @throws \Exception If an error occurs during cleaning.
     */
    public function clean(): void
    {
        $indexerPool = $this->indexerResolver->getIndexerPool();
        foreach ($indexerPool->getAll() as $id => $indexerClass) {

            if (!is_a($indexerClass, AbstractIndexer::class, true)) {
                continue;
            }

            /** @var AbstractIndexer $indexerInstance */
            $indexerInstance = $indexerPool->get($id);
            $this->cleanByIndexer($indexerInstance);
        }
    }

    /**
     * Cleans deleted items for a specific indexer.
     *
     * Iterates through all stores, sets the current store, and deletes items in bulk
     * using the provided indexer's configuration and connector. Only performs deletion
     * if the indexer configuration allows it.
     *
     * @param AbstractIndexer $indexer The indexer instance to clean deleted items for.
     * @throws LocalizedException If an error occurs during the cleaning process.
     */
    public function cleanByIndexer(AbstractIndexer $indexer): void
    {
        if (!$indexer->getIndexerConfiguration()->getAllowDelete()) {
            return;
        }

        $bulkSize = $indexer->getIndexerHelper()->getIndexerBulkSize();

        // Cycle for store and retrive configuration from indexer and set template
        foreach ($this->storeManager->getStores() as $store) {
            $this->storeManager->setCurrentStore($store);
            $connector = $indexer->getConnector();
            $indexTemplate = $indexer->getGetRemoteIndexTemplate();

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

            $itemsInBuffer = 0;
            $buffer = [];

            foreach ($indexer->getDeletedItemFinder()->discover() as $id) {
                if ($id === null) {
                    continue;
                }

                $buffer[] = $id;
                $itemsInBuffer++;
                if ($itemsInBuffer % $bulkSize === 0) {
                    $connector->delete($buffer, $collection);
                    $buffer = [];
                    $itemsInBuffer = 0;
                }
            }

            if ($itemsInBuffer > 0 && $itemsInBuffer < $bulkSize) {
                $connector->delete($buffer, $collection);
            }
        }
    }

}
