<?php

namespace CouponsPlus\App\Offers;

use WC_Coupon;
use WC_Discounts;
use CouponsPlus\Original\Collections\Collection;

#[\AllowDynamicProperties]
Class CouponCartDiscountAmount extends CouponDiscountAmount
{
    protected $originalAmountToApply;

    public function addAmount(float $amount, int $numberOfItemsAppliedTo = 0)
    {
        $this->originalAmountToApply = $amount;

        parent::addAmount($amount, $numberOfItemsAppliedTo);
    }


    public function registerEvents(): void
    {
        /**
         * Coupons+ 3 uses a custom discount type and as such we have to register a custom filter for the self::getDiscountedAmount()
         * to trigger.
         */
        if ($this->coupon->isTree()) {
            add_filter(
                'woocommerce_coupon_get_items_to_apply',
                [$this, 'addValidItemsToWCDiscounts'],
                10,
                3
            );

            add_filter(
                'woocommerce_coupon_get_apply_quantity',
                [$this, 'addValidQuantityToWCDiscounts'],
                10,
                4
            );
        }

        add_filter(
            'woocommerce_coupon_get_discount_amount',
            [$this, 'getDiscountedAmount'],
            $priority = 10,
            $numberOfArguments = 5
        );
    }

    public function unregisterEvents(): void
    {
        if ($this->coupon->isTree()) {
            // potentially we should uh, refactor the args that are repeated in  registerevents() so that the removal dont break if
            // we change them when registering the filter in the method above
            remove_filter(
                'woocommerce_coupon_get_items_to_apply',
                [$this, 'addValidItemsToWCDiscounts'],
                10
            );
        }

        remove_filter(
            'woocommerce_coupon_get_discount_amount',
            [$this, 'getDiscountedAmount'],
            $priority = 10
        );
    }

    public function addValidQuantityToWCDiscounts(int $apply_quantity, $item, WC_Coupon $coupon, WC_Discounts $WCDiscounts)
    {
        if (!$this->isOurCoupon($coupon)) {
            return $apply_quantity;
        }

        return 1; // always 1 since we are applying a discount to the cart
    }
    /**
     * Coupons+ 3 and up
     */
    public function addValidItemsToWCDiscounts(array $itemsToDiscountUsuallyEmpty, WC_Coupon $coupon, WC_Discounts $wcDiscounts) : array
    {
        if (!$this->isOurCoupon($coupon)) {
            return $itemsToDiscountUsuallyEmpty;
        }

        (object) $cartItems = Collection::create($wcDiscounts->get_items());

        return $cartItems->asArray();
    }

    public function getDiscountedAmount(float $sumOfAllDiscounts, float $discountingAmount, /*array|null*/ $cartItemArray, bool $single, \WC_Coupon $coupon) /* : float*/
    {
        (boolean) $itsTheCouponWeWant = $coupon->get_code($context = 'edit') == $this->classicCoupon->get_code($context = 'edit');

        if ($itsTheCouponWeWant) {
            $lineSubtotal = $this->extractLineSubtotal($cartItemArray);

            if ($lineSubtotal < $this->amount) {
                (float) $amountToAdd = $lineSubtotal;
            } else {
                (float) $amountToAdd = $this->amount;
            }

            $sumOfAllDiscounts += $amountToAdd;

            $this->amount = $this->amount - $amountToAdd;
        }

        return $sumOfAllDiscounts;
    }

    /**
     * Extracts the line subtotal from either a cart item array or an order item object.
     *
     * @param array|\WC_Order_Item_Product|null $item
     * @return float
     */
    protected function extractLineSubtotal($item): float
    {
        if ($item === null) {
            return 0.0;
        }

        // Order item context (WC_Order_Item_Product)
        if ($item instanceof \WC_Order_Item_Product) {
            return (float) $item->get_subtotal();
        }

        // Cart item context (array with 'line_subtotal')
        if (is_array($item) && isset($item['line_subtotal'])) {
            return (float) $item['line_subtotal'];
        }

        return 0.0;
    }
}