<?php

namespace CouponsPlus\App\Coupon\Tree\Data\Transformers;

use CouponsPlus\Original\Collections\Collection;
use CouponsPlus\App\Coupon\Tree\RawTestableDataInspector;
use CouponsPlus\App\Coupon\Tree\Data\Transformers\Abilities\DataTransformer;
use CouponsPlus\App\Coupon\Tree\Finders\Abilities\TestableRelationsDataFinder;

/**
 * Will use the testable relations finder to merge the base (parent) testable into the testable partial.
 */
class PartialTestableMergerTransformerFromRelations implements DataTransformer
{
    protected TestableRelationsDataFinder $testableRelationsDataFinder;

    public function __construct(TestableRelationsDataFinder $testableRelationsDataFinder)
    {
        $this->testableRelationsDataFinder = $testableRelationsDataFinder;
    }

    /**
     * @param object $data
     * @return object
     */
    public function transform($data) : object
    {
        $inspector = new RawTestableDataInspector($data);
        /**
         * loop through the whole structure. if you find a partial, merge it with its parent using the finder.
         */
        if ($inspector->hasChildren()) {
            $data->children = Collection::create($data->children)->map(function (object $child) {
                return $this->transform($child);
            })->asArray();
        } else {
            // no children so a testable or a partial
            if ($inspector->isPartial()) {
                $data = $this->mergeWithBase($data);
            }
        }

        return $data;
    }

    /**
     * This is a testable partial and it will be merged with its base testable if found.
     */
    private function mergeWithBase(object $data) : object
    {
        $baseTestable = $this->testableRelationsDataFinder->findParent($data->id);
        if ($baseTestable) {
            $merger = new MergeBaseTestableIntoTestablePartialTransformer($baseTestable);
            $data = $merger->transform($data);
        }

        return $data;
    }
}