package com.aps.service.Algorithm;

import com.aps.common.util.FileHelper;
import com.aps.common.util.ProductionDeepCopyUtil;
import com.aps.entity.Algorithm.Chromosome;
import com.aps.entity.Algorithm.GlobalOperationInfo;
import com.aps.entity.Algorithm.ObjectiveWeights;
import com.aps.entity.Algorithm.ScheduleParams;
import com.aps.entity.RoutingDiscreteParam;
import com.aps.entity.basic.*;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * 作者：佟礼
 * 时间：2025-11-21
 */
public class Initialization {
    private static List<Entry> allOperations;
    private static GlobalParam _globalParam;

    private static List<Order> orders;

    private static List<Machine> machines;

    private ObjectiveWeights _objectiveWeights = new ObjectiveWeights();

    private LocalDateTime baseTime ; // 当前基准时间

    public Initialization() {

    }

    public Initialization(GlobalParam globalParam,List<Entry> allOperations,List<Order> _orders,List<Machine> _machines,ObjectiveWeights objectiveWeights) {
        Initialization.allOperations = allOperations;
        _globalParam= globalParam;
        orders=_orders;
        machines=_machines;
        _objectiveWeights= objectiveWeights;
    }

    /**
     * 预生成全局工序列表（按“订单0→订单1→…+订单内工序1→2→…”排序，分配GlobalOpId）
     */
    public CopyOnWriteArrayList<GlobalOperationInfo> generateGlobalOpList() {
        CopyOnWriteArrayList<GlobalOperationInfo> globalOpList = new CopyOnWriteArrayList<>();
        int globalOpId = 0;
        for (Entry op : allOperations) {
            GlobalOperationInfo info = new GlobalOperationInfo();
            info.setGlobalOpId(globalOpId);
            info.setGroupId(op.getGroupId());
            info.setSequence(op.getSequence());
            info.setOp(op);
            globalOpList.add(info);
            globalOpId++;
        }
        return globalOpList;
    }
    /**
     * 生成初始种群
     */
    public List<Chromosome> generateInitialPopulation(ScheduleParams param, List<GlobalOperationInfo> globalOpList) {
        List<Chromosome> population = new ArrayList<>();
        // 按比例生成不同类型个体（GS:40%, LS:40%, RS:20%）
        int gsCount = (int) (param.getPopulationSize() * param.getGsRatio());
        int lsCount =gsCount+ (int) (param.getPopulationSize() * param.getLsRatio());
        int rsCount = param.getPopulationSize() - gsCount - lsCount;
        int populationSize=param.getPopulationSize();
        // 并行循环：对应 Parallel.For(0, PopulationSize, i => { ... })
        IntStream.range(0, populationSize)
                .parallel() // 开启并行
                .forEach(i -> {
                    Chromosome chromo = new Chromosome(); // 初始化染色体
                    // chromo.setObjectiveWeights(_objectiveWeights);
                    // chromo.setInitMachines(ProductionDeepCopyUtil.deepCopyList(machines));
                    chromo.setOrders(new CopyOnWriteArrayList<>(orders));
                    // 全局选择（GS）：按GlobalOpId顺序生成MachineSelection
                    if (i < gsCount) {
                        chromo.setGsOrls(1);
                        generateGSChromosome(chromo,globalOpList); // 对应 C# GenerateGSChromosome
                    } else if (i < lsCount) {
                        chromo.setGsOrls(2);
                        // 局部选择（LS）：按GlobalOpId顺序生成MachineSelection（仅负载计算范围不同）
                        generateLSChromosome(chromo,globalOpList);
                    } else {
                        chromo.setGsOrls(3);
                        //  随机选择（RS）：按GlobalOpId顺序生成MachineSelection（仅机器选择随机）
                        generateRSChromosome(chromo,globalOpList);
                    }

                    population.add(chromo); // 赋值到数组，线程安全（数组索引唯一）
                });





        return population;
    }


    public List<Chromosome> generateInitialSFPopulation(Chromosome chromo, List<GlobalOperationInfo> globalOpList) {
        List<Chromosome> population = new ArrayList<>();


        // 并行循环：对应 Parallel.For(0, PopulationSize, i => { ... })

        if (chromo.getGsOrls()==1) {
            generateGSChromosome(chromo,globalOpList); // 对应 C# GenerateGSChromosome
        } else if (chromo.getGsOrls()==2) {
            // 局部选择（LS）：按GlobalOpId顺序生成MachineSelection（仅负载计算范围不同）
            generateLSChromosome(chromo,globalOpList);
        } else {
            //  随机选择（RS）：按GlobalOpId顺序生成MachineSelection（仅机器选择随机）
            generateRSChromosome(chromo,globalOpList);
        }




        return population;
    }


    /**
     * 全局选择（GS）生成染色体（按GlobalOpId顺序生成MachineSelection）
     */
    private Chromosome generateGSChromosome(Chromosome chromosome,List<GlobalOperationInfo> globalOpList) {


        Map<Long, Double> machineLoad = new HashMap<>();
        // int[] machineLoad = new int[machineCount + 1]; // 设备负载（1-based，设备ID从1开始）
        CopyOnWriteArrayList<Integer> ms = new CopyOnWriteArrayList<>(); // MachineSelection（顺序=GlobalOpId顺序）
        CopyOnWriteArrayList<Integer> os = new CopyOnWriteArrayList<>(); // OperationSequencing
        List<Integer> osp = new ArrayList<>(); // 相同优先级OperationSequencing
        double prevPriority =(double) -1;
        Random rnd = new Random();

        // 步骤1：按GlobalOpId顺序为每道工序选择机器
        for (GlobalOperationInfo globalOp : globalOpList) {
            Entry op = globalOp.getOp();
            int groupId = globalOp.getGroupId();

            if (prevPriority != op.getPriority()) {
                prevPriority = op.getPriority();
                if (!osp.isEmpty()) {
                    // 打乱工序排序部分
                    Collections.shuffle(osp);
                    os.addAll(osp);
                    osp.clear();
                }
            }

            // 选择“设备当前负载+工序加工时间”最小的机器（全局负载均衡）
            List<MachineOption> optionalMachines = op.getMachineOptions();

            if(optionalMachines==null||optionalMachines.size()==0)
            {
                throw new RuntimeException("工序没有设置设备"+op.getOrderCode()+":"+op.getSequence());

            }

            MachineOption minLoadMachine = optionalMachines.stream()
                    .min(Comparator.comparingDouble(m ->machineLoad.getOrDefault(m.getMachineId(), (double)0) + m.getProcessingTime()))
                    .orElseThrow(() -> new NoSuchElementException("MachineOption not found for machine: " ));


            OptionalInt index = IntStream.range(0, optionalMachines.size())
                    .filter(i -> minLoadMachine.getMachineId()==optionalMachines.get(i).getMachineId())
                    .findFirst();

            // 计算该机器在“可选机器列表”中的顺序号（1-based）
            int machineSeq =index.orElse(0)+1 ;//findIndex(optionalMachines, minLoadMachine.getMachineId()) + 1;
            ms.add(machineSeq);

            // 更新设备负载
            machineLoad.put(minLoadMachine.getMachineId(),
                    machineLoad.getOrDefault(minLoadMachine.getMachineId(), (double)0) + minLoadMachine.getProcessingTime());

            osp.add(groupId);
        }

        if (!osp.isEmpty()) {
            Collections.shuffle(osp, rnd);
            os.addAll(osp);
            osp.clear();
        }

        if(chromosome.getOperationSequencing()!=null&&chromosome.getOperationSequencing().size()>0)
        {
            chromosome.getOperationSequencing().addAll(os);
            chromosome.getMachineSelection().addAll(ms);

        }else {
            // 步骤2：打乱工序排序部分（OS）
            chromosome.setOperationSequencing(shuffleWithPriority(os));

            chromosome.setMachineSelection(ms);
        }

        return chromosome;
    }

    /**
     * 局部选择（LS）生成染色体（按GlobalOpId顺序，每个订单重新初始化负载）
     */
    private Chromosome generateLSChromosome(Chromosome chromosome,List<GlobalOperationInfo> globalOpList) {


        CopyOnWriteArrayList<Integer> ms = new CopyOnWriteArrayList<>();
        CopyOnWriteArrayList<Integer> os = new CopyOnWriteArrayList<>();
        Random rnd = new Random();
        int currentOrderId = -1;
        Map<Long, Double> machineLoad = new HashMap<>();
        List<Integer> osp = new ArrayList<>();
        double prevPriority = -1;

        for (GlobalOperationInfo globalOp : globalOpList) {
            Entry op = globalOp.getOp();
            int groupId = globalOp.getGroupId();

            if (prevPriority != op.getPriority()) {
                prevPriority = op.getPriority();
                if (!osp.isEmpty()) {
                    Collections.shuffle(osp, rnd);
                    os.addAll(osp);
                    osp.clear();
                }
            }

            // 若切换到新订单，重置设备负载
            if (groupId != currentOrderId) {
                machineLoad.clear();
                currentOrderId = groupId;
            }

            // 选择“当前订单内设备负载+加工时间”最小的机器
            List<MachineOption> optionalMachines = op.getMachineOptions();

            if(optionalMachines==null||optionalMachines.size()==0)
            {
                throw new RuntimeException("工序没有设置设备"+op.getOrderCode()+":"+op.getSequence());

            }

            MachineOption minLoadMachine = optionalMachines.stream()
                    .min(Comparator.comparingDouble(m -> machineLoad.getOrDefault(m.getMachineId(), (double)0) + m.getProcessingTime()))
                    .orElseThrow(() -> new NoSuchElementException("MachineOption not found for machine: " ));


            OptionalInt index = IntStream.range(0, optionalMachines.size())
                    .filter(i -> minLoadMachine.getMachineId()==optionalMachines.get(i).getMachineId())
                    .findFirst();


            int machineSeq = index.orElse(0) + 1;
            ms.add(machineSeq);

            double maLoad=  machineLoad.getOrDefault(minLoadMachine.getMachineId(),(double)0);
            // 更新设备负载
            machineLoad.put(minLoadMachine.getMachineId(),
                    maLoad+ minLoadMachine.getProcessingTime());

            osp.add(groupId);
        }

        if (!osp.isEmpty()) {
            Collections.shuffle(osp, rnd);
            os.addAll(osp);
            osp.clear();
        }
        if(chromosome.getOperationSequencing()!=null&&chromosome.getOperationSequencing().size()>0)
        {
            chromosome.getOperationSequencing().addAll(os);
            chromosome.getMachineSelection().addAll(ms);

        }else {
            chromosome.setOperationSequencing(shuffleWithPriority(os));
            chromosome.setMachineSelection(ms);
        }

        return chromosome;
    }
    /**
     * 随机选择（RS）生成染色体（按GlobalOpId顺序，随机选择机器）
     */
    private Chromosome generateRSChromosome(Chromosome chromosome,List<GlobalOperationInfo> globalOpList) {


        CopyOnWriteArrayList<Integer> ms = new CopyOnWriteArrayList<>();
        CopyOnWriteArrayList<Integer> os = new CopyOnWriteArrayList<>();
        Random rnd = new Random();
        List<Integer> osp = new ArrayList<>();
        double prevPriority = -1;

        for (GlobalOperationInfo globalOp : globalOpList) {
            Entry op = globalOp.getOp();
            int groupId = globalOp.getGroupId();

            if (prevPriority != op.getPriority()) {
                prevPriority = op.getPriority();
                if (!osp.isEmpty()) {
                    Collections.shuffle(osp, rnd);
                    os.addAll(osp);
                    osp.clear();
                }
            }

            // 随机选择一道工序的可选机器（1-based顺序号）
            List<MachineOption> optionalMachines = op.getMachineOptions();
            if(optionalMachines==null||optionalMachines.size()==0)
            {
                throw new RuntimeException("工序没有设置设备"+op.getOrderCode()+":"+op.getSequence());

            }
            int randomSeq = rnd.nextInt(optionalMachines.size()) + 1;
            ms.add(randomSeq);

            osp.add(groupId);
        }

        if (!osp.isEmpty()) {
            Collections.shuffle(osp, rnd);
            os.addAll(osp);
            osp.clear();
        }
        if(chromosome.getOperationSequencing()!=null&&chromosome.getOperationSequencing().size()>0)
        {
            chromosome.getOperationSequencing().addAll(os);
            chromosome.getMachineSelection().addAll(ms);

        }else {
            chromosome.setOperationSequencing(shuffleWithPriority(os));
            chromosome.setMachineSelection(ms);
        }

        return chromosome;
    }

    /**
     * 使用构造启发式算法生成初始种群
     */
    public List<Chromosome> generateHeuristicInitialPopulation(ScheduleParams param,int _PopulationSize) {
        List<Chromosome> population = new ArrayList<>();
        int populationSize = param.getPopulationSize()==0?_PopulationSize:param.getPopulationSize();
        this.baseTime=param.getBaseTime();
        // 按比例生成不同启发式规则的个体（优化：增加混合策略和瓶颈优先）
        int sptCount = (int) (populationSize * 0.15);
        int eddsptCount = sptCount + (int) (populationSize * 0.15);
        int eddCount = eddsptCount + (int) (populationSize * 0.15);
        int bottleneckCount = eddCount + (int) (populationSize * 0.15);
        int sstCount = bottleneckCount + (int) (populationSize * 0.15);
        int crCount = sstCount + (int) (populationSize * 0.1);
        int lptCount = crCount + (int) (populationSize * 0.1);
        int lsCount = populationSize - lptCount;

        IntStream.range(0, populationSize)
                .parallel()
                .forEach(i -> {
                    Chromosome chromo = new Chromosome();
                    chromo.setOrders(new CopyOnWriteArrayList<>(orders));

                    if (i < sptCount) {
                        // SPT规则 // 1 SPT（最短加工时间）
                        chromo.setGenerateType("SPT");
                        generateChromosomeByType(chromo, 1);
                    } else if (i < eddsptCount) {
                        // EDD+SPT混合策略 先按截止日期，再按加工时间
                        chromo.setGenerateType("EDD+SPT");
                        generateEDDSPTChromosome(chromo);
                    } else if (i < eddCount) {
                        // EDD规则 截止时间
                        chromo.setGenerateType("EDD");

                        generateChromosomeByType(chromo, 3);
                    } else if (i < bottleneckCount) {
                        // 瓶颈优先策略
                        chromo.setGenerateType("BottleneckFirst");
                        generateBottleneckFirstChromosome(chromo);
                    } else if (i < sstCount) {
                        // SST规则（已有物料排序）：优先选择准备时间最短的工序
                        chromo.setGenerateType("SST");
                        generateSSTChromosome(chromo);
                    } else if (i < crCount) {
                        // CR规则 CR（关键比率）规则：关键比率 = (截止日期 - 当前日期) / 剩余加工时间
                        chromo.setGenerateType("CR");
                        generateCRChromosome(chromo);
                    } else if (i < lptCount) {
                        // LPT规则  2 LPT（最长加工时间）
                        chromo.setGenerateType("LPT");
                        generateChromosomeByType(chromo, 2);
                    } else {
                        // 随机规则
                        chromo.setGenerateType("LS");
                        generateLsChromosome(chromo);
                    }

                    population.add(chromo);
                });

        return population;
    }


    /**
     *  SPT（最短加工时间）
     */
    private Chromosome generateChromosomeByType(Chromosome chromosome,int sortType) {
        CopyOnWriteArrayList<Integer> ms = new CopyOnWriteArrayList<>();
        CopyOnWriteArrayList<Integer> os = new CopyOnWriteArrayList<>();
        Map<Long, Double> machineLoad = new HashMap<>();
        Random rnd = new Random();
        CopyOnWriteArrayList<GlobalOperationInfo> globalOpList = new CopyOnWriteArrayList<>();

        // 1 SPT（最短加工时间） 2 LPT（最长加工时间）
        Map<Integer, LocalDateTime> dueDateMap = new HashMap<>();
        for (Order order : orders) {
            dueDateMap.put(order.getId(), order.getDueDate());
        }

        Map<Entry, Integer> randomIds = new HashMap<>();

        List<Integer> indices = new ArrayList<>();
        for (int i = 0; i < allOperations.size(); i++) {
            indices.add(i);
        }
        Collections.shuffle(indices, rnd);
        for (int i = 0; i < allOperations.size(); i++) {
            randomIds.put(allOperations.get(i), indices.get(i));
        }
        boolean considerSequence = rnd.nextBoolean();
        List<Entry> sortedOps = new ArrayList<>(allOperations);
        if (sortType == 1 || sortType == 2) {
            if (considerSequence) {
                sortedOps.sort(Comparator.comparing((Entry op) -> op.getPriority())
                        .thenComparing(Entry::getSequence)
                        .thenComparing(op -> op.getProductId() != null ? op.getProductId() : "") // 相同物料排在一起，减少换型
                        .thenComparing(op -> {
                            if (op.getMachineOptions() == null || op.getMachineOptions().isEmpty()) {
                                return sortType == 1 ? 0.0 : Double.MAX_VALUE; // 空值默认排最前/最后
                            }
                            double time = op.getMachineOptions().get(0).getProcessingTime() * op.getQuantity();
                            return sortType == 1 ? time : -time;
                        })
                        .thenComparing(randomIds::get));
            }
            else{
                sortedOps.sort(Comparator.comparing((Entry op) -> op.getPriority())
                        .thenComparing(op -> op.getProductId() != null ? op.getProductId() : "") // 相同物料排在一起，减少换型
                        .thenComparing(op -> {
                            if (op.getMachineOptions() == null || op.getMachineOptions().isEmpty()) {
                                return sortType == 1 ? 0.0 : Double.MAX_VALUE; // 空值默认排最前/最后
                            }
                            double time = op.getMachineOptions().get(0).getProcessingTime() * op.getQuantity();
                            return sortType == 1 ? time : -time;
                        })
                        .thenComparing(randomIds::get));
            }

        } else if (sortType == 3) {
            //截止时间
            if (considerSequence) {
                sortedOps.sort(Comparator.comparing((Entry op) -> op.getPriority())
                        .thenComparing(Entry::getSequence)
                        .thenComparing(op -> op.getProductId() != null ? op.getProductId() : "") // 相同物料排在一起，减少换型
                        .thenComparing(op -> dueDateMap.get(op.getGroupId()),
                                Comparator.nullsLast(Comparator.naturalOrder()))
                        .thenComparing(randomIds::get));
            }else {
                sortedOps.sort(Comparator.comparing((Entry op) -> op.getPriority())
                        .thenComparing(op -> op.getProductId() != null ? op.getProductId() : "") // 相同物料排在一起，减少换型
                        .thenComparing(op -> dueDateMap.get(op.getGroupId()),
                                Comparator.nullsLast(Comparator.naturalOrder()))
                        .thenComparing(randomIds::get));
            }
        }
        if (_globalParam.isIsMultipleMachine()) {
            sortedOps = OperationSplitService.splitOpsForHeuristic(sortedOps, rnd);
            chromosome.setAllOperations(new CopyOnWriteArrayList<>(sortedOps));
        }

        int globalOpId = 0;
        // 为每个工序选择机器
        for (Entry op : sortedOps) {

            int groupId = op.getGroupId();

            // 选择负载最小的机器
            List<MachineOption> optionalMachines = op.getMachineOptions();
            double minLoad = optionalMachines.stream()
                    .mapToDouble(m -> machineLoad.getOrDefault(m.getMachineId(), 0.0) + m.getProcessingTime())
                    .min()
                    .orElse(Double.MAX_VALUE);

            // 找到所有负载最小的机器
            List<MachineOption> minLoadMachines = optionalMachines.stream()
                    .filter(m -> machineLoad.getOrDefault(m.getMachineId(), 0.0) + m.getProcessingTime() == minLoad)
                    .collect(Collectors.toList());

            // 随机选择一个负载最小的机器
            MachineOption selectedMachine = minLoadMachines.get(rnd.nextInt(minLoadMachines.size()));

            OptionalInt index = IntStream.range(0, optionalMachines.size())
                    .filter(i -> selectedMachine.getMachineId() == optionalMachines.get(i).getMachineId())
                    .findFirst();
            int machineSeq = index.orElse(0) + 1;
            ms.add(machineSeq);

            // 更新负载
            machineLoad.put(selectedMachine.getMachineId(),
                    machineLoad.getOrDefault(selectedMachine.getMachineId(), 0.0) + selectedMachine.getProcessingTime());

            os.add(groupId);


            GlobalOperationInfo info = new GlobalOperationInfo();
            info.setGlobalOpId(globalOpId);
            info.setGroupId(op.getGroupId());
            info.setSequence(op.getSequence());
            info.setOp(op);
            globalOpList.add(info);
            globalOpId++;

        }
        chromosome.setGlobalOpList(globalOpList);
        chromosome.setOperationSequencing(os);
        chromosome.setMachineSelection(ms);
        return chromosome;
    }

    /**
     * CR（关键比率）规则：关键比率 = (截止日期 - 当前日期) / 剩余加工时间
     * 比率越小，优先级越高
     */
    private Chromosome generateCRChromosome(Chromosome chromosome) {
        CopyOnWriteArrayList<Integer> ms = new CopyOnWriteArrayList<>();
        CopyOnWriteArrayList<Integer> os = new CopyOnWriteArrayList<>();
        Map<Long, Double> machineLoad = new HashMap<>();
        Random rnd = new Random();
        CopyOnWriteArrayList<GlobalOperationInfo> globalOpList=new CopyOnWriteArrayList<>();

        Map<Integer, Order> orderMap = new HashMap<>();
        for (Order order : orders) {
            orderMap.put(order.getId(), order);
        }

        Map<Integer, Double> remainingProcessingTime = new HashMap<>();
        for (Entry op : allOperations) {
            int groupId = op.getGroupId();
            double quantity = op.getQuantity();
            double processTime = op.getMachineOptions().get(0).getProcessingTime()*quantity;
            remainingProcessingTime.put(groupId, remainingProcessingTime.getOrDefault(groupId, 0.0) + processTime);
        }

        List<Entry> sortedOps = new ArrayList<>(allOperations);
        Map<Entry, Integer> randomIds = new HashMap<>();
        List<Integer> indices = new ArrayList<>();
        for (int i = 0; i < allOperations.size(); i++) {
            indices.add(i);
        }
        Collections.shuffle(indices, rnd);
        for (int i = 0; i < allOperations.size(); i++) {
            randomIds.put(allOperations.get(i), indices.get(i));
        }
        boolean considerSequence = rnd.nextBoolean();
        if (considerSequence) {
            sortedOps.sort(Comparator.comparing((Entry op) -> op.getPriority())
                    .thenComparing(Entry::getSequence)
                    .thenComparing(op -> op.getProductId() != null ? op.getProductId() : "") // 相同物料排在一起，减少换型
                    .thenComparing(op -> {
                        Order order = orderMap.get(op.getGroupId());
                        return calculateCriticalRatio(order, remainingProcessingTime.getOrDefault(op.getGroupId(), 0.0));
                    })
                    .thenComparing(randomIds::get));
        }else {
            sortedOps.sort(Comparator.comparing((Entry op) -> op.getPriority())
                    .thenComparing(op -> op.getProductId() != null ? op.getProductId() : "") // 相同物料排在一起，减少换型
                    .thenComparing(op -> {
                        Order order = orderMap.get(op.getGroupId());
                        return calculateCriticalRatio(order, remainingProcessingTime.getOrDefault(op.getGroupId(), 0.0));
                    })
                    .thenComparing(randomIds::get));
        }

        if (_globalParam.isIsMultipleMachine()) {
            sortedOps = OperationSplitService.splitOpsForHeuristic(sortedOps, rnd);
            chromosome.setAllOperations(new CopyOnWriteArrayList<>(sortedOps));
        }
        int globalOpId = 0;
        // 为每个工序选择机器
        for (Entry op : sortedOps) {

            int groupId = op.getGroupId();

            // 选择负载最小的机器
            List<MachineOption> optionalMachines = op.getMachineOptions();
            double minLoad = optionalMachines.stream()
                    .mapToDouble(m -> machineLoad.getOrDefault(m.getMachineId(), 0.0) + m.getProcessingTime())
                    .min()
                    .orElse(Double.MAX_VALUE);

            // 找到所有负载最小的机器
            List<MachineOption> minLoadMachines = optionalMachines.stream()
                    .filter(m -> machineLoad.getOrDefault(m.getMachineId(), 0.0) + m.getProcessingTime() == minLoad)
                    .collect(Collectors.toList());

            // 随机选择一个负载最小的机器
            MachineOption selectedMachine = minLoadMachines.get(rnd.nextInt(minLoadMachines.size()));

            OptionalInt index = IntStream.range(0, optionalMachines.size())
                    .filter(i -> selectedMachine.getMachineId() == optionalMachines.get(i).getMachineId())
                    .findFirst();
            int machineSeq = index.orElse(0) + 1;
            ms.add(machineSeq);

            // 更新负载
            machineLoad.put(selectedMachine.getMachineId(),
                    machineLoad.getOrDefault(selectedMachine.getMachineId(), 0.0) + selectedMachine.getProcessingTime());

            os.add(groupId);


            GlobalOperationInfo info = new GlobalOperationInfo();
            info.setGlobalOpId(globalOpId);
            info.setGroupId(op.getGroupId());
            info.setSequence(op.getSequence());
            info.setOp(op);
            globalOpList.add(info);
            globalOpId++;

        }
        chromosome.setGlobalOpList(globalOpList);
        chromosome.setOperationSequencing(os);
        chromosome.setMachineSelection(ms);
        return chromosome;
    }
    private double calculateCriticalRatio(Order order, double remainingTime) {
        if (order == null || order.getDueDate() == null || remainingTime <= 0) {
            return Double.MAX_VALUE;
        }

        long daysUntilDue = java.time.Duration.between(this.baseTime, order.getDueDate()).toDays();
        if (daysUntilDue <= 0) {
            return 0;
        }

        return (double) daysUntilDue / remainingTime;
    }

    /**
     * SST（最短准备时间）规则：优先选择准备时间最短的工序
     */
    private Chromosome generateSSTChromosome(Chromosome chromosome) {
        CopyOnWriteArrayList<Integer> ms = new CopyOnWriteArrayList<>();
        CopyOnWriteArrayList<Integer> os = new CopyOnWriteArrayList<>();
        Map<Long, Double> machineLoad = new HashMap<>();
        Map<Long, List<RoutingDiscreteParam>> lastDiscreteParams = new HashMap<>();
        Random rnd = new Random();
        CopyOnWriteArrayList<GlobalOperationInfo> globalOpList=new CopyOnWriteArrayList<>();

        List<Entry> sortedOps = new ArrayList<>(allOperations);
        Map<Entry, Integer> randomIds = new HashMap<>();
        List<Integer> indices = new ArrayList<>();
        for (int i = 0; i < allOperations.size(); i++) {
            indices.add(i);
        }
        Collections.shuffle(indices, rnd);
        for (int i = 0; i < allOperations.size(); i++) {
            randomIds.put(allOperations.get(i), indices.get(i));
        }

        sortedOps.sort(Comparator.comparing((Entry op) -> op.getPriority())
                .thenComparing(op -> op.getProductId() != null ? op.getProductId() : "")
                .thenComparing(op -> op.getMachineOptions().get(0).getProcessingTime() * op.getQuantity())
                .thenComparing(randomIds::get));

        if (_globalParam.isIsMultipleMachine()) {
            sortedOps = OperationSplitService.splitOpsForHeuristic(sortedOps, rnd);
            chromosome.setAllOperations(new CopyOnWriteArrayList<>(sortedOps));
        }

        int globalOpId = 0;
        for (Entry op : sortedOps) {

            int groupId = op.getGroupId();

            List<MachineOption> optionalMachines = op.getMachineOptions();

            MachineOption bestMachine = optionalMachines.stream()
                    .min((m1, m2) -> {
                        double cost1 = calculateSSTCost(m1, machineLoad, lastDiscreteParams, op);
                        double cost2 = calculateSSTCost(m2, machineLoad, lastDiscreteParams, op);
                        return Double.compare(cost1, cost2);
                    })
                    .orElseThrow(() -> new NoSuchElementException("MachineOption not found"));

            OptionalInt index = IntStream.range(0, optionalMachines.size())
                    .filter(i -> bestMachine.getMachineId() == optionalMachines.get(i).getMachineId())
                    .findFirst();
            int machineSeq = index.orElse(0) + 1;
            ms.add(machineSeq);

            machineLoad.put(bestMachine.getMachineId(),
                    machineLoad.getOrDefault(bestMachine.getMachineId(), 0.0) + bestMachine.getProcessingTime());
            if (op.getDiscreteParameter() != null && !op.getDiscreteParameter().isEmpty()) {
                lastDiscreteParams.put(bestMachine.getMachineId(), op.getDiscreteParameter());
            }

            os.add(groupId);

            GlobalOperationInfo info = new GlobalOperationInfo();
            info.setGlobalOpId(globalOpId);
            info.setGroupId(op.getGroupId());
            info.setSequence(op.getSequence());
            info.setOp(op);
            globalOpList.add(info);
            globalOpId++;
        }
        chromosome.setGlobalOpList(globalOpList);
        chromosome.setOperationSequencing(os);
        chromosome.setMachineSelection(ms);
        return chromosome;
    }
    private String getDiscreteParamsKey(Entry op) {
        List<RoutingDiscreteParam> params = op.getDiscreteParameter();
        if (params == null || params.isEmpty()) {
            return "";
        }
        List<RoutingDiscreteParam> sortedParams = new ArrayList<>(params);
        sortedParams.sort(Comparator.comparing(RoutingDiscreteParam::getParameterName));
        StringBuilder sb = new StringBuilder();
        for (RoutingDiscreteParam p : sortedParams) {
            sb.append(p.getGroupName() != null ? p.getGroupName() : "")
                    .append("|")
                    .append(p.getParameterName() != null ? p.getParameterName() : "")
                    .append("|")
                    .append(";");
        }
        return sb.toString();
    }

    private double calculateSSTCost(MachineOption machine, Map<Long, Double> machineLoad,
                                    Map<Long, List<RoutingDiscreteParam>> lastDiscreteParams, Entry op) {
        double loadCost = machineLoad.getOrDefault(machine.getMachineId(), 0.0);
        double processingCost = machine.getProcessingTime() * op.getQuantity();

        double setupCost = 0;
        List<RoutingDiscreteParam> lastParams = lastDiscreteParams.get(machine.getMachineId());
        if (lastParams != null && op.getDiscreteParameter() != null) {
            boolean needSetup = false;
            for (RoutingDiscreteParam param : op.getDiscreteParameter()) {
                boolean foundMatch = false;
                for (RoutingDiscreteParam lastParam : lastParams) {
                    if (param.getGroupName().equals(lastParam.getGroupName())
                            && param.getParameterName().equals(lastParam.getParameterName())) {
                        foundMatch = true;
                        break;
                    }
                }
                if (!foundMatch) {
                    needSetup = true;
                    break;
                }
            }
            if (needSetup) {
                setupCost = 3600;
            }
        }

        return loadCost + processingCost + setupCost;
    }

    /**
     *  EDD+SPT混合策略：先按截止日期，再按加工时间
     */
    private Chromosome generateEDDSPTChromosome(Chromosome chromosome) {
        CopyOnWriteArrayList<Integer> ms = new CopyOnWriteArrayList<>();
        CopyOnWriteArrayList<Integer> os = new CopyOnWriteArrayList<>();
        Map<Long, Double> machineLoad = new HashMap<>();
        Random rnd = new Random();
        CopyOnWriteArrayList<GlobalOperationInfo> globalOpList = new CopyOnWriteArrayList<>();

        Map<Integer, LocalDateTime> dueDateMap = new HashMap<>();
        for (Order order : orders) {
            dueDateMap.put(order.getId(), order.getDueDate());
        }

        Map<Entry, Integer> randomIds = new HashMap<>();
        List<Integer> indices = new ArrayList<>();
        for (int i = 0; i < allOperations.size(); i++) {
            indices.add(i);
        }
        Collections.shuffle(indices, rnd);
        for (int i = 0; i < allOperations.size(); i++) {
            randomIds.put(allOperations.get(i), indices.get(i));
        }

        List<Entry> sortedOps = new ArrayList<>(allOperations);
        boolean considerSequence = rnd.nextBoolean();
        if (considerSequence) {
            sortedOps.sort(Comparator.comparing((Entry op) -> op.getPriority())
                    .thenComparing(Entry::getSequence)
                    .thenComparing(op -> dueDateMap.get(op.getGroupId()),
                            Comparator.nullsLast(Comparator.naturalOrder()))
                    .thenComparing(op -> op.getProductId() != null ? op.getProductId() : "")
                    .thenComparing(op -> {
                        if (op.getMachineOptions() == null || op.getMachineOptions().isEmpty()) {
                            return 0.0;
                        }
                        return op.getMachineOptions().get(0).getProcessingTime() * op.getQuantity();
                    })
                    .thenComparing(randomIds::get));
        } else {
            sortedOps.sort(Comparator.comparing((Entry op) -> op.getPriority())
                    .thenComparing(op -> dueDateMap.get(op.getGroupId()),
                            Comparator.nullsLast(Comparator.naturalOrder()))
                    .thenComparing(op -> op.getProductId() != null ? op.getProductId() : "")
                    .thenComparing(op -> {
                        if (op.getMachineOptions() == null || op.getMachineOptions().isEmpty()) {
                            return 0.0;
                        }
                        return op.getMachineOptions().get(0).getProcessingTime() * op.getQuantity();
                    })
                    .thenComparing(randomIds::get));
        }
        if (_globalParam.isIsMultipleMachine()) {
            sortedOps = OperationSplitService.splitOpsForHeuristic(sortedOps, rnd);
            chromosome.setAllOperations(new CopyOnWriteArrayList<>(sortedOps));
        }
        int globalOpId = 0;
        for (Entry op : sortedOps) {
            int groupId = op.getGroupId();
            List<MachineOption> optionalMachines = op.getMachineOptions();
            double minLoad = optionalMachines.stream()
                    .mapToDouble(m -> machineLoad.getOrDefault(m.getMachineId(), 0.0) + m.getProcessingTime())
                    .min()
                    .orElse(Double.MAX_VALUE);

            List<MachineOption> minLoadMachines = optionalMachines.stream()
                    .filter(m -> machineLoad.getOrDefault(m.getMachineId(), 0.0) + m.getProcessingTime() == minLoad)
                    .collect(Collectors.toList());

            MachineOption selectedMachine = minLoadMachines.get(rnd.nextInt(minLoadMachines.size()));
            OptionalInt index = IntStream.range(0, optionalMachines.size())
                    .filter(i -> selectedMachine.getMachineId() == optionalMachines.get(i).getMachineId())
                    .findFirst();
            int machineSeq = index.orElse(0) + 1;
            ms.add(machineSeq);

            machineLoad.put(selectedMachine.getMachineId(),
                    machineLoad.getOrDefault(selectedMachine.getMachineId(), 0.0) + selectedMachine.getProcessingTime());

            os.add(groupId);

            GlobalOperationInfo info = new GlobalOperationInfo();
            info.setGlobalOpId(globalOpId);
            info.setGroupId(op.getGroupId());
            info.setSequence(op.getSequence());
            info.setOp(op);
            globalOpList.add(info);
            globalOpId++;
        }
        chromosome.setGlobalOpList(globalOpList);
        chromosome.setOperationSequencing(os);
        chromosome.setMachineSelection(ms);
        return chromosome;
    }

    /**
     *  瓶颈优先策略：优先安排预计为瓶颈的设备上的工序
     */
    private Chromosome generateBottleneckFirstChromosome(Chromosome chromosome) {
        CopyOnWriteArrayList<Integer> ms = new CopyOnWriteArrayList<>();
        CopyOnWriteArrayList<Integer> os = new CopyOnWriteArrayList<>();
        Map<Long, Double> machineLoad = new HashMap<>();
        Random rnd = new Random();
        CopyOnWriteArrayList<GlobalOperationInfo> globalOpList = new CopyOnWriteArrayList<>();

        Map<Entry, Integer> randomIds = new HashMap<>();
        List<Integer> indices = new ArrayList<>();
        for (int i = 0; i < allOperations.size(); i++) {
            indices.add(i);
        }
        Collections.shuffle(indices, rnd);
        for (int i = 0; i < allOperations.size(); i++) {
            randomIds.put(allOperations.get(i), indices.get(i));
        }

        List<Entry> sortedOps = new ArrayList<>(allOperations);

        Map<Long, Integer> machineOperationCount = new HashMap<>();
        Map<Long, Double> machineTotalTime = new HashMap<>();
        for (Entry op : allOperations) {
            if (op.getMachineOptions() != null && !op.getMachineOptions().isEmpty()) {
                for (MachineOption mo : op.getMachineOptions()) {
                    machineOperationCount.put(mo.getMachineId(),
                            machineOperationCount.getOrDefault(mo.getMachineId(), 0) + 1);
                    machineTotalTime.put(mo.getMachineId(),
                            machineTotalTime.getOrDefault(mo.getMachineId(), 0.0)
                                    + mo.getProcessingTime() * op.getQuantity());
                }
            }
        }

        sortedOps.sort(Comparator.comparing((Entry op) -> op.getPriority())
                .thenComparing((Entry op) -> {
                    if (op.getMachineOptions() == null || op.getMachineOptions().isEmpty()) {
                        return 0.0;
                    }
                    double maxTime = 0;
                    for (MachineOption mo : op.getMachineOptions()) {
                        double time = machineTotalTime.getOrDefault(mo.getMachineId(), 0.0);
                        if (time > maxTime) maxTime = time;
                    }
                    return -maxTime;
                })
                .thenComparing(op -> op.getProductId() != null ? op.getProductId() : "")
                .thenComparing(randomIds::get));
        if (_globalParam.isIsMultipleMachine()) {
            sortedOps = OperationSplitService.splitOpsForHeuristic(sortedOps, rnd);
            chromosome.setAllOperations(new CopyOnWriteArrayList<>(sortedOps));
        }
        int globalOpId = 0;
        for (Entry op : sortedOps) {
            int groupId = op.getGroupId();
            List<MachineOption> optionalMachines = op.getMachineOptions();
            double minLoad = optionalMachines.stream()
                    .mapToDouble(m -> machineLoad.getOrDefault(m.getMachineId(), 0.0) + m.getProcessingTime())
                    .min()
                    .orElse(Double.MAX_VALUE);

            List<MachineOption> minLoadMachines = optionalMachines.stream()
                    .filter(m -> machineLoad.getOrDefault(m.getMachineId(), 0.0) + m.getProcessingTime() == minLoad)
                    .collect(Collectors.toList());

            MachineOption selectedMachine = minLoadMachines.get(rnd.nextInt(minLoadMachines.size()));
            OptionalInt index = IntStream.range(0, optionalMachines.size())
                    .filter(i -> selectedMachine.getMachineId() == optionalMachines.get(i).getMachineId())
                    .findFirst();
            int machineSeq = index.orElse(0) + 1;
            ms.add(machineSeq);

            machineLoad.put(selectedMachine.getMachineId(),
                    machineLoad.getOrDefault(selectedMachine.getMachineId(), 0.0) + selectedMachine.getProcessingTime());

            os.add(groupId);

            GlobalOperationInfo info = new GlobalOperationInfo();
            info.setGlobalOpId(globalOpId);
            info.setGroupId(op.getGroupId());
            info.setSequence(op.getSequence());
            info.setOp(op);
            globalOpList.add(info);
            globalOpId++;
        }
        chromosome.setGlobalOpList(globalOpList);
        chromosome.setOperationSequencing(os);
        chromosome.setMachineSelection(ms);
        return chromosome;
    }

    /**
     *  随机
     */
    private Chromosome generateLsChromosome(Chromosome chromosome) {
        CopyOnWriteArrayList<Integer> ms = new CopyOnWriteArrayList<>();
        CopyOnWriteArrayList<Integer> os = new CopyOnWriteArrayList<>();
        Map<Long, Double> machineLoad = new HashMap<>();
        Random rnd = new Random();
        CopyOnWriteArrayList<GlobalOperationInfo> globalOpList = new CopyOnWriteArrayList<>();
        // 按加工时间排序工序，加工时间相同时随机排序
        List<Entry> sortedOps = new ArrayList<>(allOperations);
        Map<Entry, Integer> randomIds = new HashMap<>();
        List<Integer> indices = new ArrayList<>();
        for (int i = 0; i < allOperations.size(); i++) {
            indices.add(i);
        }
        Collections.shuffle(indices, rnd);
        for (int i = 0; i < allOperations.size(); i++) {
            randomIds.put(allOperations.get(i), indices.get(i));
        }
        sortedOps.sort(Comparator.comparing((Entry op) -> op.getPriority())
                .thenComparing(op -> op.getProductId() != null ? op.getProductId() : "") // 相同物料排在一起，减少换型
                .thenComparing(randomIds::get));

        if (_globalParam.isIsMultipleMachine()) {
            sortedOps = OperationSplitService.splitOpsForHeuristic(sortedOps, rnd);
            chromosome.setAllOperations(new CopyOnWriteArrayList<>(sortedOps));
        }


        int globalOpId = 0;
        // 为每个工序选择机器
        for (Entry op : sortedOps) {

            int groupId = op.getGroupId();

            // 选择负载最小的机器
            List<MachineOption> optionalMachines = op.getMachineOptions();
            double minLoad = optionalMachines.stream()
                    .mapToDouble(m -> machineLoad.getOrDefault(m.getMachineId(), 0.0) + m.getProcessingTime())
                    .min()
                    .orElse(Double.MAX_VALUE);

            // 找到所有负载最小的机器
            List<MachineOption> minLoadMachines = optionalMachines.stream()
                    .filter(m -> machineLoad.getOrDefault(m.getMachineId(), 0.0) + m.getProcessingTime() == minLoad)
                    .collect(Collectors.toList());

            // 随机选择一个负载最小的机器
            MachineOption selectedMachine = minLoadMachines.get(rnd.nextInt(minLoadMachines.size()));

            OptionalInt index = IntStream.range(0, optionalMachines.size())
                    .filter(i -> selectedMachine.getMachineId() == optionalMachines.get(i).getMachineId())
                    .findFirst();
            int machineSeq = index.orElse(0) + 1;
            ms.add(machineSeq);

            // 更新负载
            machineLoad.put(selectedMachine.getMachineId(),
                    machineLoad.getOrDefault(selectedMachine.getMachineId(), 0.0) + selectedMachine.getProcessingTime());

            os.add(groupId);


            GlobalOperationInfo info = new GlobalOperationInfo();
            info.setGlobalOpId(globalOpId);
            info.setGroupId(op.getGroupId());
            info.setSequence(op.getSequence());
            info.setOp(op);
            globalOpList.add(info);
            globalOpId++;

        }
        chromosome.setGlobalOpList(globalOpList);
        chromosome.setOperationSequencing(os);
        chromosome.setMachineSelection(ms);
        return chromosome;
    }


    /**
     * 按优先级加权打乱工序排序（高优先级订单的工序更可能靠前）
     */
    private CopyOnWriteArrayList<Integer> shuffleWithPriority(List<Integer> os) {

        if (!_globalParam.isIsBreakPriority()) {
            return new CopyOnWriteArrayList<>(os);
        }

        Random rnd = new Random();
        double maxPriority = allOperations.stream()
                .mapToDouble(Entry::getPriority)
                .max()
                .orElse(0) + 1;

        // 为每个工序分配权重：低优先级订单的工序权重更高
        List<WeightedGroup> weightedOs = os.stream()
                .map(groupId -> {
                    Entry entry = allOperations.stream()
                            .filter(o -> o.getGroupId() == groupId)
                            .findFirst().orElse(null);

                    return new WeightedGroup(groupId, maxPriority - entry.getPriority());
                })
                .collect(Collectors.toList());

        // 按权重随机排序（权重越高，被选中的概率越大）
        CopyOnWriteArrayList<Integer> shuffled = new CopyOnWriteArrayList<>();
        while (!weightedOs.isEmpty()) {
            double totalWeight = weightedOs.stream().mapToDouble(WeightedGroup::getWeight).sum();
            int randomWeight = rnd.nextInt((int)totalWeight);
            int cumulativeWeight = 0;
            int selectedIndex = -1;

            for (int i = 0; i < weightedOs.size(); i++) {
                cumulativeWeight += weightedOs.get(i).getWeight();
                if (cumulativeWeight >= randomWeight) {
                    selectedIndex = i;
                    break;
                }
            }

            shuffled.add(weightedOs.get(selectedIndex).getGroupId());
            weightedOs.remove(selectedIndex);
        }

        return shuffled;
    }
    /**
     * HybridAlgorithm 专用混合初始种群
     * 先用 CP-SAT 生成高质量种子，剩余用原有构造启发式补足
     */
    public List<Chromosome> generateHybridInitialPopulation(ScheduleParams param) {
        int populationSize =param.getPopulationSize();
        this.baseTime = param.getBaseTime();

        CopyOnWriteArrayList<GlobalOperationInfo> sharedGlobalOpList = generateGlobalOpList();

        List<Chromosome> population = new ArrayList<>(populationSize);

        int cpSatTarget = Math.min(Math.max(populationSize / 5, 2), 6);
        int timeBudgetSec = Math.max(populationSize * 2, 15);

        CpSatInitializer cpSatInit = new CpSatInitializer(
                allOperations, machines, orders, param.getBaseTime());

        List<Chromosome> cpSatResults = cpSatInit.generate(
                sharedGlobalOpList, cpSatTarget, timeBudgetSec);

        if (!cpSatResults.isEmpty()) {
            for (Chromosome chromo : cpSatResults) {
                chromo.setOrders(new CopyOnWriteArrayList<>(orders));
                chromo.setGlobalOpList(deepCopyGlobalOpList(sharedGlobalOpList));
                PriorityCheckResult r = Initialization.checkPriorityOrder(chromo);
//                if (r.isPerfect()) {
//                    population.add(chromo);
//
//                }

            }
            population.addAll(cpSatResults);
            FileHelper.writeLogFile(
                    "[Hybrid初始化] CP-SAT贡献 " + cpSatResults.size() + " 个高质量种子");
        }

        int remaining = populationSize - population.size();
        if (remaining > 0) {
            ScheduleParams subParam = new ScheduleParams();
            subParam.setPopulationSize(remaining);
            subParam.setBaseTime(param.getBaseTime());

            List<Chromosome> heuristicPopulation =
                    generateHeuristicInitialPopulation(subParam,remaining);
            for (Chromosome chromo : heuristicPopulation) {

if(chromo!=null)
{
    chromo.setOrders(new CopyOnWriteArrayList<>(orders));
    population.add(chromo);
}

            }

        }

        long cpSatCount = population.stream()
                .filter(c -> c.getGsOrls() == 4).count();
        FileHelper.writeLogFile(String.format(
                "[Hybrid初始化] 总种群=%d, CP-SAT=%d, 启发式=%d",
                population.size(), cpSatCount,
                population.size() - cpSatCount));

        return population;
    }
    private CopyOnWriteArrayList<GlobalOperationInfo> deepCopyGlobalOpList(
            CopyOnWriteArrayList<GlobalOperationInfo> source) {
        CopyOnWriteArrayList<GlobalOperationInfo> copy = new CopyOnWriteArrayList<>();
        for (GlobalOperationInfo info : source) {
            GlobalOperationInfo newInfo = new GlobalOperationInfo();
            newInfo.setGlobalOpId(info.getGlobalOpId());
            newInfo.setGroupId(info.getGroupId());
            newInfo.setSequence(info.getSequence());
            newInfo.setOp(info.getOp());
            copy.add(newInfo);
        }
        return copy;
    }
    /**
     * 检查染色体的operationSequencing是否遵守Priority排序
     * Priority值越小优先级越高（1最先排，99最后排）
     *
     * @param chromo 待检查的染色体
     * @return PriorityCheckResult 包含违反次数、严重度、详细报告
     */
    public static PriorityCheckResult checkPriorityOrder(Chromosome chromo) {
        List<GlobalOperationInfo> globalOpList = chromo.getGlobalOpList();
        List<Integer> os = chromo.getOperationSequencing();

        if (os == null || os.isEmpty() || globalOpList == null || globalOpList.isEmpty()) {
            return new PriorityCheckResult(0, 0, 0, "无数据");
        }

        Map<Integer, Double> groupPriority = new HashMap<>();
        Map<Integer, List<Entry>> groupOps = new HashMap<>();
        for (GlobalOperationInfo info : globalOpList) {
            int gid = info.getGroupId();
            groupPriority.putIfAbsent(gid, info.getOp().getPriority());
            groupOps.computeIfAbsent(gid, k -> new ArrayList<>()).add(info.getOp());
        }

        int violationCount = 0;
        int totalSeverity = 0;
        double maxSingleSeverity = 0;
        StringBuilder detail = new StringBuilder();

        for (int i = 0; i < os.size() - 1; i++) {
            int gidA = os.get(i);
            int gidB = os.get(i + 1);

            if (gidA == gidB) continue;

            double priA = groupPriority.getOrDefault(gidA, Double.MAX_VALUE);
            double priB = groupPriority.getOrDefault(gidB, Double.MAX_VALUE);

            if (priA > priB) {
                double severity = priA - priB;
                violationCount++;
                totalSeverity += severity;
                maxSingleSeverity = Math.max(maxSingleSeverity, severity);

                if (detail.length() < 800) {
                    detail.append(String.format(
                            "  [%d→%d] groupId=%d(优先级%d) 排在 groupId=%d(优先级%d) 之前，差距=%d\n",
                            i, i + 1, gidA, priA, gidB, priB, severity));
                }
            }
        }

        String report = String.format(
                "Priority检查: 违反次数=%d, 总严重度=%d, 最大单次差距=%f, " +
                        "工序组数=%d, 不同优先级组数=%d\n%s",
                violationCount, totalSeverity, maxSingleSeverity,
                groupPriority.size(), new HashSet<>(groupPriority.values()).size(),
                detail.toString());

        return new PriorityCheckResult(violationCount, totalSeverity,
                maxSingleSeverity, report);
    }

    /**
     * Priority检查结果
     */
    public static class PriorityCheckResult {
        public final int violationCount;
        public final int totalSeverity;
        public final double maxSingleSeverity;
        public final String report;

        PriorityCheckResult(int violationCount, int totalSeverity,
                            double maxSingleSeverity, String report) {
            this.violationCount = violationCount;
            this.totalSeverity = totalSeverity;
            this.maxSingleSeverity = maxSingleSeverity;
            this.report = report;
        }

        public boolean isPerfect() {
            return violationCount == 0;
        }

        @Override
        public String toString() {
            return report;
        }
    }
    /**
     * 辅助类：用于权重排序
     */
    private static class WeightedGroup {
        private final int groupId;
        private final double weight;

        public WeightedGroup(int groupId, double weight) {
            this.groupId = groupId;
            this.weight = weight;
        }

        public int getGroupId() {
            return groupId;
        }

        public double getWeight() {
            return weight;
        }
    }

}
