<?php

namespace CouponsPlus\App\Coupon\Tree\Factories;

use CouponsPlus\App\Conditions\Condition;
use CouponsPlus\Original\Collections\Collection;
use CouponsPlus\App\Coupon\Abilities\DashboardCard;
use CouponsPlus\App\Conditions\ConditionsRegistrator;
use CouponsPlus\App\Conditions\Filter;
use CouponsPlus\App\Conditions\FiltersRegistrator;
use CouponsPlus\App\Coupon\Tree\Abilities\CardData;
use CouponsPlus\App\Coupon\Tree\Abilities\TestableData;
use CouponsPlus\App\Offers\Offer;
use CouponsPlus\App\Offers\OffersRegistrator;
use WC_Coupon;

use function WC;

class ConditionFilterOrOfferFromDataFactory
{
    private $classicCoupon;

    public function __construct(?WC_Coupon $classicCoupon = null)
    {
        $this->classicCoupon = $classicCoupon;
    } 

    /** 
     * @return Filter|Condition|Offer
     * @param  TestableData|CardData $testableData TestableData = condition or filter, CardData = offer, i know this shouldve been a different class but its been so much i dont got no time for that right now
     */
    public function create(string $cardType, /*TestableData|CardData*/ $testableData)
    {
        // get the type (filter or condition)
        // then get the subtype (like inCategroies)
        // and use to get it from the BuiltInFiltersRegistrator or BuiltInConditionsRegistrator
        switch($cardType) {
            case 'offer':
                (object) $RegisteredComponentsClass = OffersRegistrator::class;
            break;
            case 'filter':
                (object) $RegisteredComponentsClass = FiltersRegistrator::class;
            break;
            case 'condition':
                (object) $RegisteredComponentsClass = ConditionsRegistrator::class;
            break;
        }

        (string) $Component = $RegisteredComponentsClass::get()->all()->get($testableData->getType());
        //VERY IMPORTANT: WE NEED TO CONVERT IT TO ARRAYS SO THAT MAPPEDOBJECTS MAY BE PARSED CORRECTLY
        (object) $nativeOptions = $testableData->getOptions()->asArrayWithNativeValues();
        
        /**
         * This should be its own class but i have no time rn 
         */
        switch ($cardType) {
            case 'offer':
                $testable = new $Component($nativeOptions);

                $testable->setCoupon($this->classicCoupon);
                $testable->setCart(WC()->cart);
                break;
            case 'filter': 
                (object) $testable = new $Component($nativeOptions);
            break;
            case 'condition': 
                (object) $testable = new $Component($nativeOptions, $this->classicCoupon);
            break;
        }

        $testable->setID($testableData->getID());

        /**
         * 3.0 and up
         */
        if (method_exists($testable, 'afterFullLoad')) {
            $testable->afterFullLoad();
        }

        return $testable;
    }

    public function createFromTestableDataCollection(Collection $testableDatas) : Collection
    {
        return $testableDatas->map(
            function (TestableData $testableData) :  DashboardCard {
                return $this->create(
                    $testableData->getTestableType(),
                    $testableData
                );
            }
        );
    }
}