package com.gxwebsoft.shop.util;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;

/**
 * Utility to traverse an upstream "parent" chain and pick the nearest N users matching a predicate.
 * <p>
 * Typical usage: starting from buyerUserId, walk level-1 referee chain upwards and pick the first
 * two store-role users (type=1).
 */
public final class UpstreamUserFinder {

    private UpstreamUserFinder() {
    }

    /**
     * Walk the upstream chain starting from {@code startUserId} (exclusive), repeatedly resolving
     * the parent via {@code parentResolver}. Collect the first {@code needCount} userIds that match
     * {@code matcher}, preserving encounter order (nearest first).
     */
    public static List<Integer> findFirstNMatchingUpstreamUsers(
        Integer startUserId,
        int needCount,
        int maxDepth,
        Function<Integer, Integer> parentResolver,
        Predicate<Integer> matcher
    ) {
        if (startUserId == null || needCount <= 0 || maxDepth <= 0 || parentResolver == null || matcher == null) {
            return Collections.emptyList();
        }

        List<Integer> result = new ArrayList<>(Math.min(needCount, 4));
        Set<Integer> visited = new HashSet<>();

        Integer current = startUserId;
        for (int depth = 0; depth < maxDepth && current != null && result.size() < needCount; depth++) {
            Integer parentId = parentResolver.apply(current);
            if (parentId == null) {
                break;
            }
            if (!visited.add(parentId)) {
                break;
            }

            if (matcher.test(parentId)) {
                result.add(parentId);
            }
            current = parentId;
        }

        return result;
    }
}

