<?php

namespace CouponsPlus\App\Offers\BuiltIn;

use CouponsPlus\App\Offers\Offer;
use CouponsPlus\App\Conditions\CartItem;
use CouponsPlus\App\Conditions\ItemsSet;
use CouponsPlus\App\Quantities\AmountValidator;
use CouponsPlus\Original\Collections\Collection;
use CouponsPlus\Original\Collections\Mapper\Types;
use CouponsPlus\App\Offers\CouponItemDiscountAmount;
use CouponsPlus\App\Coupon\Tree\Finders\Sets\OfferItems;
use CouponsPlus\App\Coupon\Tree\Factories\StandaloneProductionTestableGroupFactory;

/**
 * This class is for internal use only and is a composition offer for bogos.
 */
#[\AllowDynamicProperties]
Class FixedPriceInternal extends Offer
{
    const TYPE = 'FixedPrice';

    public static function getName() : string
    {
        return __('FP-INTERNAL', 'coupons-plus-for-woocommerce');
    }

    public static function getDescription() : string
    {
        return __('FP-INTERNAL', 'coupons-plus-for-woocommerce');
    }

    static public function getIconUrl(): string
    {
        return '';
    }

    public static function getOptions() : Collection
    {
        return new Collection([
            'amount' => Types::FLOAT()->meta([])
        ]);
    }

    public function setCoupon(\WC_Coupon $coupon)
    {
        parent::setCoupon(...func_get_args());

        $this->testableGroupFactory = new StandaloneProductionTestableGroupFactory($this->coupon);
    }

    public function apply(ItemsSet $itemsSet)
    {
        $this->generateUNIQUEKeyForThisDiscount();

        $itemsSet->getItems()->filter([$this, 'canApplyDiscountTo'])
            ->forEvery(function (CartItem $cartItem) {
                (integer) $quantity = $cartItem->getState('quantity');
                (float) $individualPrice = $cartItem->getProduct()->get_price($context = 'edit');
                (float) $discountPerItem = $individualPrice - $this->options->amount;

                if ($quantity) {
                    (object) $couponDiscount = new CouponItemDiscountAmount($this->coupon);
                    $couponDiscount->addCartItemKey($cartItem->getState('key'));
                    // this key identifies this unique Discount for all CouponItemDiscountAmount instances
                    $couponDiscount->setUniqueKey($this->uniqueKey);

                    $couponDiscount->addAmount(
                        $discountPerItem * $quantity,
                        1 // setting the $quanity fails
                    );
                }
            });
    }

    public function canApplyDiscountTo(CartItem $item) : bool
    {
        /**
         * Amount validator to deal with floatvals
         */
        $minAmountValidator = new AmountValidator([
            'quantity' => [
                'type' => 'minimum',
                'amount' => $this->options->amount,
            ],
        ]);

        $equalsAmountValidator = new AmountValidator([
            'quantity' => [
                'type' => 'equals',
                'amount' => $this->options->amount,
            ],
        ]);

        $equalsAmountValidator->setAmount($item->getProduct()->get_price('edit'));
        $minAmountValidator->setAmount($item->getProduct()->get_price('edit'));

        // only those that cost more than the price per item
        return $minAmountValidator->isValid() && !$equalsAmountValidator->isValid();
    }

    protected function generateUNIQUEKeyForThisDiscount(): void
    {
        $this->uniqueKey = uniqid(wp_rand(), true);
    }
}
