<?php

namespace FiloBlu\Refilo\Remote\Entity\Provider;

use FiloBlu\Refilo\Remote\Entity\AbstractEntity;
use FiloBlu\Refilo\Remote\Entity\Category;
use FiloBlu\Refilo\Remote\Entity\EntityProviderInterface;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\App\ResourceConnection;
use Magento\Store\Api\Data\StoreInterface;
use Magento\Store\Api\Data\WebsiteInterface;
use Zend_Db;
use Zend_Db_Expr;

use function count;

/**
 * Class CategoryPermissionsProvider
 * @package FiloBlu\Refilo\Remote\Entity\Provider
 */
class CategoryPermissionsProvider extends BaseProvider
{
    /**
     * @var int
     */
    protected $website;

    /**
     * @var ResourceConnection
     */
    protected $resourceConnection;

    /**
     * CategoryPermissionsProvider constructor.
     * @param ResourceConnection $resourceConnection
     * @param ScopeConfigInterface $scopeConfig
     */
    public function __construct(
        ResourceConnection $resourceConnection,
        ScopeConfigInterface $scopeConfig
    ) {
        parent::__construct($scopeConfig);
        $this->resourceConnection = $resourceConnection;
    }

    /**
     *
     */
    #[\ReturnTypeWillChange]
    public function rewind()
    {
        $connection = $this->resourceConnection->getConnection();

        if (!$connection->isTableExists('magento_catalogpermissions_index')) {
            $this->items = [];
            return;
        }

        $select = $this->getSelect();

        $result = $connection->fetchAll($select, [], Zend_Db::FETCH_ASSOC);

        foreach ($result as $permission) {
            $hasPermission = (bool)$permission['has_permission'];

            if (!isset($this->items[$permission['category_id']])) {
                $this->items[$permission['category_id']] = new Category([
                    AbstractEntity::ID    => (string)$permission['category_id'],
                    Category::PERMISSIONS => []
                ]);
            }

            if (!$hasPermission) {
                continue;
            }

            $this->items[$permission['category_id']]->addPermission($permission);
        }

        if (!$this->hasReadHandler()) {
            return;
        }

        // TODO: Handle pagination
        $this->getReadHandler()->onRead($this->items, count($this->items), $this->getReadHandlerArguments());
    }

    /**
     * @param array $ids
     * @return $this|EntityProviderInterface
     */
    public function withIds(array $ids): EntityProviderInterface
    {
        $this->ids = $ids;
        return $this;
    }

    /**
     * @param StoreInterface $store
     * @return $this|EntityProviderInterface
     */
    public function forStore(StoreInterface $store): EntityProviderInterface
    {
        $this->website = $store->getWebsiteId();
        return $this;
    }

    /**
     * @param WebsiteInterface $website
     * @return $this|EntityProviderInterface
     */
    public function forWebsite(WebsiteInterface $website): EntityProviderInterface
    {
        $this->website = $website->getId();
        return $this;
    }

    /**
     * @return \Magento\Framework\DB\Select
     */
    public function getSelect()
    {
        return $this->resourceConnection->getConnection()
            ->select()
            ->from(
                ['cce' => 'catalog_category_entity'],
                ['category_id' => 'entity_id']
            )->joinLeft(
                ['mci' => 'magento_catalogpermissions_index'],
                "mci.category_id = cce.entity_id AND mci.website_id = $this->website",
                [
                    'website_id'                  => 'website_id',
                    'has_permission'              => new Zend_Db_Expr('IF(category_id IS NULL, 0, 1)'),
                    'customer_group_id'           => 'customer_group_id',
                    'grant_catalog_category_view' => 'grant_catalog_category_view',
                    'grant_catalog_product_price' => 'grant_catalog_product_price',
                    'grant_checkout_items'        => 'grant_checkout_items'
                ]
            );
    }

    /**
     * @return \Generator
     * @throws \Zend_Db_Statement_Exception
     */
    public function toGenerator(): \Generator
    {
        $connection = $this->resourceConnection->getConnection();

        if (!$connection->isTableExists('magento_catalogpermissions_index')) {
            yield null;
        }

        $select = $this->getSelect()->order('cce.entity_id ASC');

        $statement = $this->resourceConnection->getConnection()->query($select);

        $prevCategoryId = null;
        $category = null;
        while (($row = $statement->fetch(Zend_Db::FETCH_ASSOC))) {
            if ($prevCategoryId !== $row['category_id']) {
                if ($prevCategoryId !== null) {
                    yield $prevCategoryId => $category;
                }

                $category = new Category([
                    AbstractEntity::ID    => (string)$row['category_id'],
                    Category::PERMISSIONS => []
                ]);
            }

            $hasPermission = (bool)$row['has_permission'];
            if ($hasPermission) {
                $category->addPermission($row);
            }

            $prevCategoryId = $category->getId();
        }

        yield $prevCategoryId => $category;
    }
}
