<?php
/**
 * @author 1902 Software
 * @copyright Copyright © 2023 1902 Software (https://1902software.com/magento/)
 * @package WriteTextAI_WriteTextAI
 */

namespace WriteTextAI\WriteTextAI\Setup\Patch\Data;

use Magento\Authorization\Model\ResourceModel\Role\CollectionFactory as RoleCollectionFactory;
use Magento\Authorization\Model\RulesFactory;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\Patch\DataPatchInterface;

class AddReviewerApiPermissionDataPatch implements DataPatchInterface
{
    /**
     * @var ModuleDataSetupInterface
     */
    private $moduleDataSetup;

    /**
     * @var RoleCollectionFactory
     */
    private $roleCollectionFactory;

    /**
     * @var RulesFactory
     */
    private $rulesFactory;

    /**
     * @param ModuleDataSetupInterface $moduleDataSetup
     * @param RoleCollectionFactory $roleCollectionFactory
     * @param RulesFactory $rulesFactory
     */
    public function __construct(
        ModuleDataSetupInterface $moduleDataSetup,
        RoleCollectionFactory $roleCollectionFactory,
        RulesFactory $rulesFactory
    ) {
        $this->moduleDataSetup = $moduleDataSetup;
        $this->roleCollectionFactory = $roleCollectionFactory;
        $this->rulesFactory = $rulesFactory;
    }

    /**
     * Apply data patch
     *
     * @return void
     */
    public function apply()
    {
        $roleCollection = $this->roleCollectionFactory->create();
        $roleCollection->addFieldToFilter('role_name', AddReviewerRoleDataPatch::REVIEWER_ROLE);
        $roleCollection->setOrder('role_id', 'DESC');

        $role = $roleCollection->getFirstItem();

        if (!$role || !$role->getId()) {
            return;
        }

        if ($this->doRulesMatch((int) $role->getId(), AddReviewerRoleDataPatch::EXPECTED_RESOURCES)) {
            return;
        }

        $connection = $this->moduleDataSetup->getConnection();
        $connection->delete(
            $this->moduleDataSetup->getTable('authorization_rule'),
            ['role_id = ?' => (int) $role->getId()]
        );

        $this->rulesFactory->create()
            ->setRoleId((int) $role->getId())
            ->setResources(AddReviewerRoleDataPatch::EXPECTED_RESOURCES)
            ->saveRel();
    }

    /**
     * Check if rules match expected resources
     *
     * @param int $roleId
     * @param array $expectedResources
     * @return bool
     */
    private function doRulesMatch(int $roleId, array $expectedResources): bool
    {
        $connection = $this->moduleDataSetup->getConnection();
        $select = $connection->select()
            ->from($this->moduleDataSetup->getTable('authorization_rule'), ['resource_id'])
            ->where('role_id = ?', $roleId);

        $currentResources = $connection->fetchCol($select);

        sort($currentResources);
        sort($expectedResources);

        return $currentResources === $expectedResources;
    }

    /**
     * Get dependencies
     *
     * @return array
     */
    public static function getDependencies()
    {
        return [
            AddReviewerRoleDataPatch::class
        ];
    }

    /**
     * Get aliases
     *
     * @return array
     */
    public function getAliases()
    {
        return [];
    }
}
