<?php
/**
 * Copyright 2024 Adobe
 * All Rights Reserved.
 */
declare(strict_types=1);

namespace Magento\DataExporter\Model\Indexer;

use Magento\DataExporter\Model\FailedItemsRegistry;
use Magento\Framework\App\ObjectManager;

class IndexStateProvider
{
    public const INSERT_OPERATION = 1;
    public const UPDATE_OPERATION = 2;

    /**
     * @param FeedIndexMetadata $metadata
     * @param ?FailedItemsRegistry $failedRegistry
     */
    public function __construct(FeedIndexMetadata $metadata, ?FailedItemsRegistry $failedRegistry = null)
    {
        $this->batchSize = $metadata->getBatchSize();
        $failedRegistry ??= ObjectManager::getInstance()->get(FailedItemsRegistry::class);
        $failedRegistry->clear();
    }

    /**
     * @var int
     */
    private int $batchSize;

    /**
     * @var array
     */
    private array $feedItems = [];

    /**
     * @var array
     */
    private array $feedItemsUpdates = [];

    /**
     * @var array
     */
    private array $processedHashes = [];

    /**
     * Add new feed items suitable for insert operation
     *
     * @param array $feedItems
     * @return void
     */
    public function addItems(array $feedItems): void
    {
        $this->feedItems = array_merge($this->feedItems, $feedItems);
    }

    /**
     * Add updated feed items suitable for update operation
     *
     * @param array $feedItems
     * @return void
     */
    public function addUpdates(array $feedItems): void
    {
        $this->feedItemsUpdates = array_merge($this->feedItemsUpdates, $feedItems);
    }

    /**
     * Warning: this function is NOT idempotent
     *
     * @return array
     */
    public function getFeedItems(): array
    {
        $feedItems = [];
        $batchLimitReached = false;
        while ($item = array_shift($this->feedItems)) {
            $item['operation'] = self::INSERT_OPERATION;
            $feedItems[] = $item;
            if (count($feedItems) === $this->batchSize) {
                $batchLimitReached = true;
                break;
            }
        }
        if (!$batchLimitReached) {
            while ($item = array_shift($this->feedItemsUpdates)) {
                $item['operation'] = self::UPDATE_OPERATION;
                $feedItems[] = $item;
                if (count($feedItems) === $this->batchSize) {
                    break;
                }
            }
        }
        return $feedItems;
    }

    /**
     * Check if the batch limit is reached
     *
     * @return bool
     */
    public function isBatchLimitReached(): bool
    {
        $batchSize = count($this->feedItems) + count($this->feedItemsUpdates);
        return $batchSize >= $this->batchSize;
    }

    /**
     * Get processed hashes from the registry
     *
     * @return array
     */
    public function getProcessedHashes(): array
    {
        $processedHashes = $this->processedHashes;
        $this->processedHashes = [];
        return $processedHashes;
    }

    /**
     * Add processed hash to the registry
     *
     * @param string $hash
     * @return void
     */
    public function addProcessedHash(string $hash): void
    {
        $this->processedHashes[$hash] = true;
    }

    /**
     * Check operation type
     *
     * @param array $item
     * @return bool
     * phpcs:disable Magento2.Functions.StaticFunction
     */
    public static function isUpdate(array $item): bool
    {
        return $item['operation'] === self::UPDATE_OPERATION;
    }
}
