<?php

namespace CouponsPlus\App\Coupon\Tree\Finders\Sets;

use CouponsPlus\App\Conditions\ItemsSet;
use CouponsPlus\App\Coupon\CartComponentsSet;
use CouponsPlus\App\Coupon\Tree\Abilities\CardData;
use CouponsPlus\App\Coupon\Tree\Abilities\OfferData;
use CouponsPlus\App\Coupon\Tree\Abilities\TestableData;
use CouponsPlus\Original\Collections\Collection;

/**
 * This is actually only one offer now, since the engine was designed to support multiple offers per node and
 * this is the implementation we went with, but currently we only do one offer per node internally, even though the ui allows for more.
 *
 * We are using this class because of how coupled it is with the architecture of the engine, and we absolutely cannot afford a rewrite.
 *
 * So this will have to do for now, perhaps we can refactor it once we have a working poc.
 */
class OffersDataSet extends CartComponentsSet
{
    protected ?string $originId = null;

    /**
     * This class has some duplication wit OffersSet. It was not that well-thought-out, but it'll have to do for now...
     */
    public function __construct(...$parameters)
    {
        $itemsSet = new ItemsSet([]);
        $this->offerItems = new OfferItems($itemsSet);

        parent::__construct($parameters);
    }

    public function setOriginId(?string $originId): void
    {
        $this->originId = $originId;
    }

    public function getOriginId(): ?string
    {
        return $this->originId;
    }

    /**
     * This because now we only have one offer per set. we should refactor later once we have a working poc.
     */
    public function getOffer(): CardData
    {
        /** @var CardData $offerData */
        return $this->getItems()->first();
    }

    /**
     * This bag contains both the items to discount and the items not to discount but that they were used to make the
     * offer eligible, usually used to exclude them from offer calculations.
     */
    public function getOfferItems(): OfferItems
    {
        return $this->offerItems;
    }

    /**
     * These are the items to discount, left here because of bc.
     * @param ItemsSet $itemsSet
     * @return void
     */
    public function setItemsSet(ItemsSet $itemsSet): void
    {
        $this->offerItems->setItemsToDiscount($itemsSet);
    }

    /**
     * These are the items to discount
     * @return ItemsSet
     */
    public function getItemsSet() : ItemsSet
    {
        return $this->offerItems->getItemsToDiscount();
    }

    public function setOfferItems(OfferItems $offerItems): void
    {
        $this->offerItems = $offerItems;
        $this->getItemsSet()->setOfferItems($this->offerItems);
    }

    /**
     * This includes both items to discount and items used to make the offer eligible.
     * If either of those collections has any items, this will return true.
     * @return bool
     */
    public function hasAnyItems(): bool
    {
        return $this->offerItems->getItemsToDiscount()->haveAny() || $this->offerItems->getItemsUsedToMakeTheOfferEligibleOnly()->haveAny();
    }


    protected function getInitialItemsCollection(array $items) : Collection
    {
        return (new Collection($items))->filter(function($offerData) {
            return $offerData instanceof CardData;
        });
    }

    public function isRecursive(): bool
    {
        /** @var CardData $offerData */
        (object) $offerData = $this->getItems()->first();

        return $offerData->getOptions()->__BASE__->isRecursive ?? false;
    }
}