public static function prefetchByLevel(array $instances, PrefetchInterface $prefetcher,
                                           Prefetch $lookup, $level): array
    {
        $additionaLookups = [];
        /** @var $relQs QuerysetInterface used to fetch related records */
        /** @var callable
         * a call back that returns the value of the related model, given a model
         * e.g. if we are fetching all roles belonging to a user, this callable will return the value of
         * user in the role model pass
         */
        /** @var callable
         * a callable that returns value of the instance, e.g. value of a user
         */
        $resp = $prefetcher->getPrefetchQueryset($instances, $lookup->getCurrentQueryset($level));
        list($relQs, $valOnRelatedCallable, $valOnInstanceCallable, $isMany, $cachename) = $resp;

        $relatedObjects = $relQs->getResults();

        $relMap = [];
        foreach ($relatedObjects as $relatedObject) {
            $relAttrVal = $valOnRelatedCallable($relatedObject);
            $relMap[$relAttrVal][] = $relatedObject;
        }

        list($toAttr, $hasAsAttr) = $lookup->getCurrentToAttr($level);
        /** @var $instance Model */
        foreach ($instances as $instance) {
            $instanceVal = $valOnInstanceCallable($instance);
            $vals = ArrayHelper::getValue($relMap, $instanceVal, []);

            if (!$isMany) {
                $val = $vals ? $vals[0] : null;
                if ($hasAsAttr) {
                    $instance->{$toAttr} = $val;
                } else {
                    // so we store using the cachename
                    $instance->_valueCache[$cachename] = $val;
                }
            } else {
                if ($hasAsAttr) {
                    $instance->{$toAttr} = $vals;
                } else {
                    /** @var $manger ManagerInterface */
                    $manger = $instance->{$toAttr};
                    $qs = $manger->getQueryset();
                    $qs->_prefetchRelatedDone = true;
                    $qs->_resultsCache = $vals;
                    $instance->_prefetchedObjectCaches[$cachename] = $qs;
                }
            }
        }

        return [$relatedObjects, $additionaLookups];
    }