<?php

declare(strict_types=1);

/**
 * Apply discount-scope filtering per quote item.
 */

namespace Autogedal\PromoRules\Plugin\SalesRule\Model;

use Autogedal\PromoRules\Model\Rule\PolicyManager;
use Closure;
use Magento\Quote\Model\Quote\Item\AbstractItem;
use Magento\SalesRule\Model\RulesApplier;
use Magento\SalesRule\Model\Rule;

/**
 * Filters discount rules per item so already-discounted products are skipped only for that item.
 */
class RulesApplierPlugin
{
    /**
     * @param PolicyManager $policyManager
     */
    public function __construct(
        private readonly PolicyManager $policyManager
    ) {
    }

    /**
     * Remove rules that should not apply to the current quote item.
     *
     * @param RulesApplier $subject
     * @param Closure $proceed
     * @param AbstractItem $item
     * @param array $rules
     * @param bool $skipValidation
     * @param array $couponCodes
     * @return array
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     */
    public function aroundApplyRules(
        RulesApplier $subject,
        Closure $proceed,
        $item,
        $rules,
        $skipValidation,
        array $couponCodes = []
    ): array {
        if (!$item instanceof AbstractItem || !is_array($rules) || $rules === []) {
            return $proceed($item, $rules, $skipValidation, $couponCodes);
        }

        $address = $item->getAddress();
        if ($address === null) {
            return $proceed($item, $rules, $skipValidation, $couponCodes);
        }

        $filteredRules = [];
        foreach ($rules as $rule) {
            if (!$rule instanceof Rule) {
                $filteredRules[] = $rule;
                continue;
            }

            if ($this->policyManager->canApplyRuleToItem($rule, $item, $address)) {
                $filteredRules[] = $rule;
            }
        }

        return $proceed($item, $filteredRules, $skipValidation, $couponCodes);
    }
}
