package com.gxwebsoft.shop.util;

import org.junit.jupiter.api.Test;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;

import static org.junit.jupiter.api.Assertions.assertEquals;

class UpstreamUserFinderTest {

    @Test
    void findFirstNMatchingUpstreamUsers_skipsNonMatchingAndKeepsOrder() {
        // 100 -> 101 -> 102 -> 103 -> null
        Map<Integer, Integer> parent = Map.of(
            100, 101,
            101, 102,
            102, 103
        );
        Set<Integer> shopRoleUsers = Set.of(102, 103);

        Function<Integer, Integer> parentResolver = parent::get;
        Predicate<Integer> matcher = shopRoleUsers::contains;

        List<Integer> got = UpstreamUserFinder.findFirstNMatchingUpstreamUsers(100, 2, 20, parentResolver, matcher);
        assertEquals(List.of(102, 103), got);
    }

    @Test
    void findFirstNMatchingUpstreamUsers_returnsSingleWhenOnlyOneMatchExists() {
        // 200 -> 201 -> 202 -> null
        Map<Integer, Integer> parent = Map.of(
            200, 201,
            201, 202
        );
        Set<Integer> shopRoleUsers = Set.of(201);

        List<Integer> got = UpstreamUserFinder.findFirstNMatchingUpstreamUsers(200, 2, 20, parent::get, shopRoleUsers::contains);
        assertEquals(List.of(201), got);
    }

    @Test
    void findFirstNMatchingUpstreamUsers_stopsOnCycle() {
        // 300 -> 301 -> 302 -> 301 (cycle)
        Map<Integer, Integer> parent = Map.of(
            300, 301,
            301, 302,
            302, 301
        );
        Set<Integer> shopRoleUsers = Set.of(301, 302);

        List<Integer> got = UpstreamUserFinder.findFirstNMatchingUpstreamUsers(300, 2, 20, parent::get, shopRoleUsers::contains);
        assertEquals(List.of(301, 302), got);
    }

    @Test
    void findFirstNMatchingUpstreamUsers_returnsEmptyForNullStart() {
        List<Integer> got = UpstreamUserFinder.findFirstNMatchingUpstreamUsers(null, 2, 20, x -> null, x -> true);
        assertEquals(List.of(), got);
    }
}

