package com.aps.service.Algorithm;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 作者：佟礼
 * 时间：2026-01-27
 */
public class TestSortService {
    public  void test() {
        List<DataNode> list = new ArrayList<>();
        // 初始化数据
        list.add(new DataNode(1, 18000, 1, 1));
        list.add(new DataNode(2, 882000, 1, 2));
        list.add(new DataNode(3, 2260078, 2, 1));
        list.add(new DataNode(4, 2695678, 2, 2));
        list.add(new DataNode(5, 0, 3, 1));
        list.add(new DataNode(6, 950400, 3, 2));
        list.add(new DataNode(7, 0, 4, 1));
        list.add(new DataNode(8, 18000, 4, 2));
        list.add(new DataNode(9, 3419998, 5, 1));
        list.add(new DataNode(10, 1022646, 5, 2));

        // 1. 预处理：计算每个 groupId 对应的最小时间（作为该组的排位基准）
        Map<Integer, Long> groupMinTimeMap = list.stream()
                .collect(Collectors.groupingBy(
                        DataNode::getGroupId,
                        Collectors.mapping(DataNode::getTime, Collectors.minBy(Long::compare))
                ))
                .entrySet().stream()
                .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().orElse(0L)));

        // 2. 执行排序
        list.sort((a, b) -> {
            // 首先比较所属组的基准时间
            long minTimeA = groupMinTimeMap.get(a.getGroupId());
            long minTimeB = groupMinTimeMap.get(b.getGroupId());

            if (minTimeA != minTimeB) {
                return Long.compare(minTimeA, minTimeB);
            }

            // 如果基准时间相同（比如 group3 和 group4 都是 0），则按 groupId 排序(可选)
            if (a.getGroupId() != b.getGroupId()) {
                return Integer.compare(a.getGroupId(), b.getGroupId());
            }

            // 同一组内，按 no 升序
            return Integer.compare(a.getNo(), b.getNo());
        });

        // 输出结果
        System.out.println("ID\ttime\tgroupid\tno");
        list.forEach(System.out::println);
    }

    public static List<DataNode> customSort(List<DataNode> dataList) {
        // 按groupId分组
        Map<Integer, List<DataNode>> groupMap = dataList.stream()
                .collect(Collectors.groupingBy(data -> data.groupId));

        // 对每个组内的数据按no升序排序
        groupMap.values().forEach(group ->
                group.sort(Comparator.comparingInt(data -> data.no))
        );

        // 计算每个组的最小时间（用于组间排序）
        Map<Integer, Long> groupMinTime = new HashMap<>();
        for (Map.Entry<Integer, List<DataNode>> entry : groupMap.entrySet()) {
            long minTime = entry.getValue().stream()
                    .mapToLong(data -> data.time)
                    .min()
                    .orElse(Long.MAX_VALUE);
            groupMinTime.put(entry.getKey(), minTime);
        }

        // 将组按最小时间排序，然后展开
        return groupMap.entrySet().stream()
                .sorted(Map.Entry.comparingByValue((list1, list2) ->
                        Long.compare(groupMinTime.get(list1.get(0).groupId),
                                groupMinTime.get(list2.get(0).groupId))))
                .flatMap(entry -> entry.getValue().stream())
                .collect(Collectors.toList());
    }

    // 更简洁的写法
    public static List<DataNode> customSort2(List<DataNode> dataList) {
        // 按groupId分组并在组内按no排序
        Map<Integer, List<DataNode>> groupMap = dataList.stream()
                .collect(Collectors.groupingBy(
                        data -> data.groupId,
                        Collectors.collectingAndThen(
                                Collectors.toList(),
                                list -> {
                                    list.sort(Comparator.comparingInt(d -> d.no));
                                    return list;
                                }
                        )
                ));

        // 将组转为列表并按组内最小时间排序
        List<List<DataNode>> sortedGroups = new ArrayList<>(groupMap.values());
        sortedGroups.sort(Comparator.comparing(
                group -> group.stream().mapToLong(d -> d.time).min().orElse(Long.MAX_VALUE)
        ));

        // 展开所有组
        return sortedGroups.stream()
                .flatMap(List::stream)
                .collect(Collectors.toList());
    }
    public static List<DataNode> sortData(List<DataNode> data) {
        // 步骤1: 找出每个groupid的最小time
        Map<Integer, Integer> groupMinTime = data.stream()
                .collect(Collectors.groupingBy(
                        item -> item.groupId,
                        Collectors.mapping(item -> item.time,
                                Collectors.collectingAndThen(
                                        Collectors.toList(),
                                        list -> list.stream().min(Integer::compareTo).orElse(0)
                                ))
                ));

        // 步骤2: 按照以下规则排序
        List<DataNode> sorted = new ArrayList<>(data);
        sorted.sort((a, b) -> {
            int aMinTime = groupMinTime.get(a.groupId);
            int bMinTime = groupMinTime.get(b.groupId);

            // 首先按照group的最小time排序
            if (aMinTime != bMinTime) {
                return Integer.compare(aMinTime, bMinTime);
            }

            // 如果group最小time相同，按groupid排序
            if (a.groupId != b.groupId) {
                return Integer.compare(a.groupId, b.groupId);
            }

            // 同一个group内，按no排序
            return Integer.compare(a.no, b.no);
        });

        return sorted;
    }

    public  void test1() {
        // 创建测试数据
        List<DataNode> originalData = Arrays.asList(
                new DataNode(1, 18000, 1, 1),
                new DataNode(2, 882000, 1, 2),
                new DataNode(3, 2260078, 2, 1),
                new DataNode(4, 2695678, 2, 2),
                new DataNode(5, 0, 3, 1),
                new DataNode(6, 950400, 3, 2),
                new DataNode(7, 0, 4, 1),
                new DataNode(8, 18000, 4, 2),
                new DataNode(9, 3419998, 5, 1),
                new DataNode(10, 1022646, 5, 2)
        );

        System.out.println("排序前:");
        originalData.forEach(System.out::println);

        System.out.println("\n排序后:");
        List<DataNode> sortedData = sortData(originalData);
        sortedData.forEach(System.out::println);
    }


}
