package com.aps.service.Algorithm;

import com.aps.common.util.FileHelper;
import com.aps.common.util.ProductionDeepCopyUtil;
import com.aps.common.util.SpringContextUtil;
import com.aps.entity.Algorithm.*;
import com.aps.entity.Algorithm.IDAndChildID.GroupResult;
import com.aps.entity.DiscreteParameterDuration;
import com.aps.entity.ProdEquipment;
import com.aps.entity.Routingsupporting;
import com.aps.entity.Stock;
import com.aps.entity.basic.*;
import com.aps.service.DiscreteParameterDurationService;
import com.aps.service.DiscreteParameterMatrixService;
import com.aps.service.plan.MachineSchedulerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.server.DelegatingServerHttpResponse;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.IntStream;

/**
 * 作者：佟礼
 * 时间：2025-11-24
 */



public class GeneticDecoder {
    // private final Map<String, Chromosome> decodingCache = new HashMap<>();
    private final ConcurrentHashMap<String, Chromosome> decodingCache = new ConcurrentHashMap<>();

    // 缓存大小限制
    private static final int MAX_CACHE_SIZE = 3000;
    // 线程安全锁：避免多线程下缓存操作冲突（可选，若单线程可移除）
    // private final ReentrantLock cacheLock = new ReentrantLock();
    private LocalDateTime baseTime;

    // 性能日志辅助方法
    private static String fmtMs(long nano) {
        if (nano < 1000000L) return (nano / 1000L) + "μs";
        if (nano < 1000000000L) return (nano / 1000000L) + "ms";
        return String.format("%.2fs", nano / 1_000_000_000.0);
    }
    private final List<Machine> machines;
    private final MachineSchedulerService machineScheduler;
    private final List<Order> orders;
    private int orderMaxID;
    private final TreeMap<String, Material> materials;
    private List<Entry> _allOperations;
    private GlobalParam _globalParam;
    private MachineCalculator machineCalculator;

    private  GeneticDecoderBom bom;

    private MaterialRequirementService materialRequirementService;


    private DiscreteParameterMatrixService discreteParameterMatrixService;

    private  String sceneId;
    private boolean rebuildStructureForCurrentDecode = true;



    public GeneticDecoder(GlobalParam globalParam,LocalDateTime baseTime, List<Machine> machines, List<Order> orders,
                          TreeMap<String, Material> materials, MachineSchedulerService machineScheduler, MaterialRequirementService _materialRequirementService,String _sceneId) {
        this.baseTime = baseTime;
        this.machines = machines;
        this.orders = orders;
        this.orders.forEach(t -> t.setSYQuantity(t.getQuantity()));
        this.materials = materials;
        this.machineScheduler = machineScheduler;
        _globalParam=globalParam;
        machineCalculator=new MachineCalculator(baseTime,machines,machineScheduler);
        materialRequirementService=_materialRequirementService;

        bom=new GeneticDecoderBom(this.baseTime,machineCalculator,materialRequirementService);
        sceneId=_sceneId;
        // this.orderMaxID = orders.stream().mapToInt(Order::getId).max().orElse(0);
    }

    private final ExecutorService decodeExecutor = new ThreadPoolExecutor(
            Runtime.getRuntime().availableProcessors() - 1, // 核心线程数=CPU-1，无切换开销
            Runtime.getRuntime().availableProcessors() - 1, // 最大线程数=核心数
            0L, TimeUnit.MILLISECONDS,
            new ArrayBlockingQueue<>(200), // 有界队列，避免内存溢出
            new ThreadPoolExecutor.CallerRunsPolicy() // 任务满了主线程执行，不丢失任务
    );

    public   void  Chromosomedecode(List<Chromosome> population)
    {
        FileHelper.writeLogFile("解码---------------"+population.size() );

        boolean ismore=false;
        if(ismore) {
            CompletableFuture.allOf(population.stream()
                            .map(chromosome -> CompletableFuture.runAsync(() -> decodeChromosomeWithCache(chromosome,false), decodeExecutor))
                            .toArray(CompletableFuture[]::new))
                    .join();

        } else  {
            if (population != null && population.size() > 0) {
                population.forEach(chromosome -> {
                    decodeChromosomeWithCache( chromosome,false);
                });
            }
        }


    }

//    public Chromosome decodeChromosomeWithCache(Chromosome chromosome) {
//        String cacheKey = createCacheKey(chromosome);
//       // FileHelper.writeLogFile("解码-----------开始-------"+chromosome.getID()+":"+cacheKey );
//
//       // _allOperations=chromosome.getAllOperations();
//
//
//
//        // 1. 创建缓存键
//
//
//        // 2. 尝试从缓存获取（加锁保证线程安全）
//        cacheLock.lock();
//        try {
//            if (decodingCache.containsKey(cacheKey)) {
//                // 缓存命中：复用缓存结果
//                Chromosome cachedResult = decodingCache.get(cacheKey);
//                // 赋值给染色体
//               // chromosome.setInitMachines(ProductionDeepCopyUtil.deepCopyList(cachedResult.getInitMachines(),Machine.class));
//
//                chromosome.setObjectives(cachedResult.getObjectives());
//                chromosome.setMakespan(cachedResult.getMakespan());
//                chromosome.setTotalFlowTime(cachedResult.getTotalFlowTime());
//                chromosome.setTotalChangeoverTime(cachedResult.getTotalChangeoverTime());
//                chromosome.setMachineLoadStd(cachedResult.getMachineLoadStd());
//                chromosome.setDelayTime(cachedResult.getDelayTime());
//                chromosome.setResult(ProductionDeepCopyUtil.deepCopyList(cachedResult.getResult(),GAScheduleResult.class));
//                chromosome.setOrders(ProductionDeepCopyUtil.deepCopyList(cachedResult.getOrders(),Order.class));
//                chromosome.setOperatRel(ProductionDeepCopyUtil.deepCopyList(cachedResult.getOperatRel(), GroupResult.class));
//                chromosome.setAllOperations(ProductionDeepCopyUtil.deepCopyList(cachedResult.getAllOperations(),Entry.class));
//                chromosome.setGlobalOpList(ProductionDeepCopyUtil.deepCopyList(cachedResult.getGlobalOpList(),GlobalOperationInfo.class));
//                chromosome.setOperationSequencing(ProductionDeepCopyUtil.deepCopyList(cachedResult.getOperationSequencing()));
//                chromosome.setMachineSelection(ProductionDeepCopyUtil.deepCopyList(cachedResult.getMachineSelection()));
//
//                // Chromosome chromosomen= ProductionDeepCopyUtil.deepCopy(cachedResult);
//              //  FileHelper.writeLogFile("解码-----------结束-------"+chromosome.getID());
//
//                return chromosome;
//            }
//        } finally {
//            cacheLock.unlock(); // 确保锁释放
//        }
//        // 3. 缓存未命中：执行解码逻辑
//        decode(chromosome);
//
//        // 4. 将解码结果存入缓存（加锁保证线程安全）
//        cacheLock.lock();
//        try {
//            // 存储缓存：封装为 CacheValue 对象
//            decodingCache.put(
//                    cacheKey,
//                    chromosome
//            );
//
//            // 5. 限制缓存大小（超过 1000 移除最早插入的键）
//            if (decodingCache.size() > MAX_CACHE_SIZE) {
//
//                Iterator<String> keyIterator = decodingCache.keySet().iterator();
//                if (keyIterator.hasNext()) {
//                    keyIterator.next(); // 获取首个键
//                    keyIterator.remove(); // 移除首个键（对应 C# _decodingCache.Keys.First()）
//                }
//            }
//        } finally {
//            cacheLock.unlock();
//        }
//       // FileHelper.writeLogFile("解码-----------结束-------"+chromosome.getID());
//        return  chromosome;
//    }

    public Chromosome decodeChromosomeWithCache(Chromosome chromosome,boolean isParallel) {
        String cacheKey = createCacheKey(chromosome);
        // FileHelper.writeLogFile("解码-----------开始-------"+chromosome.getID()+":"+cacheKey );

        // _allOperations=chromosome.getAllOperations();



        // 1. 创建缓存键


        // 2. 尝试从缓存获取（无锁，ConcurrentHashMap 线程安全）
        Chromosome cachedResult = decodingCache.get(cacheKey);
        if (cachedResult != null) {
            // 缓存命中：复用缓存结果
            // 赋值给染色体
            // chromosome.setInitMachines(ProductionDeepCopyUtil.deepCopyList(cachedResult.getInitMachines(),Machine.class));
            chromosome.setFitnessLevel(cachedResult.getFitnessLevel());
            chromosome.setFitness(cachedResult.getFitness());
            chromosome.setObjectives(cachedResult.getObjectives());
            chromosome.setMakespan(cachedResult.getMakespan());
            chromosome.setTotalFlowTime(cachedResult.getTotalFlowTime());
            chromosome.setTotalChangeoverTime(cachedResult.getTotalChangeoverTime());
            chromosome.setMachineLoadStd(cachedResult.getMachineLoadStd());
            chromosome.setDelayTime(cachedResult.getDelayTime());
            chromosome.setResult(ProductionDeepCopyUtil.deepCopyList(cachedResult.getResult(),GAScheduleResult.class));
            chromosome.setOrders(ProductionDeepCopyUtil.deepCopyList(cachedResult.getOrders(),Order.class));
            chromosome.setOperatRel(ProductionDeepCopyUtil.deepCopyList(cachedResult.getOperatRel(), GroupResult.class));
            chromosome.setAllOperations(ProductionDeepCopyUtil.deepCopyList(cachedResult.getAllOperations(),Entry.class));
            chromosome.setGlobalOpList(ProductionDeepCopyUtil.deepCopyList(cachedResult.getGlobalOpList(),GlobalOperationInfo.class));
            chromosome.setOperationSequencing(ProductionDeepCopyUtil.deepCopyList(cachedResult.getOperationSequencing(), Integer.class));
            chromosome.setMachineSelection(ProductionDeepCopyUtil.deepCopyList(cachedResult.getMachineSelection(), Integer.class));

            // Chromosome chromosomen= ProductionDeepCopyUtil.deepCopy(cachedResult);
            //  FileHelper.writeLogFile("解码-----------结束-------"+chromosome.getID());

            return chromosome;
        }
        // 3. 缓存未命中：执行解码逻辑
        decode(chromosome,isParallel);

        // 4. 将解码结果存入缓存（无锁，ConcurrentHashMap 线程安全）
        decodingCache.putIfAbsent(cacheKey, chromosome);

        // 5. 限制缓存大小（超过 1000 移除最早插入的键）

        if (decodingCache.size() > MAX_CACHE_SIZE) {
            // 保留最近使用的1000个元素，移除其余的
            Iterator<Map.Entry<String, Chromosome>> iterator = decodingCache.entrySet().iterator();
            int removeCount = 0;
            while (iterator.hasNext() && removeCount < MAX_CACHE_SIZE - 1000) {
                iterator.next();
                iterator.remove();
                removeCount++;
            }
        }
        // FileHelper.writeLogFile("解码-----------结束-------"+chromosome.getID());
        return  chromosome;
    }

    public int generateGlobalOpList(Chromosome chromosome) {

        // 没有工序时无需生成半成品全局工序，避免后续重建 operationSequencing。
        if (chromosome == null || chromosome.getAllOperations() == null || chromosome.getAllOperations().isEmpty()) {
            return 0;
        }

        CopyOnWriteArrayList<Entry> allOperations= chromosome.getAllOperations()
                .stream()
                .filter(t->t.isNewCreate()==true)
                .collect(Collectors.toCollection(CopyOnWriteArrayList::new));

        // 没有新增工序时直接返回，不触发 CreateNewOpSequence 重建排序。
        if(allOperations==null||allOperations.size()==0)
        {
            return 0;
        }

        List<GlobalOperationInfo> globalOpList = new ArrayList<>();
        int globalOpId = chromosome.getGlobalOpList()
                .stream()
                .mapToInt(GlobalOperationInfo::getGlobalOpId)
                .max().orElse(0)+1;


        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++;
        }
        Initialization initialization=new Initialization();
        initialization.generateInitialSFPopulation(chromosome,globalOpList);
        chromosome.getGlobalOpList().addAll(globalOpList);
        return 1;
    }

    private void   CreateNewOpSequence(Chromosome chromosome,Map<Integer, Integer> orderDueDate,Map<Integer, List<Entry>> entrysBygroupId,boolean isJit)
    {

        //成品订单
        List<Integer> finishedOrder = chromosome.getOrders().stream()
                .filter(t-> t.getFinishOrderId()==null||t.getFinishOrderId().size()==0)
                .map(Order::getId)
                .distinct()
                .collect(Collectors.toList());

        if(finishedOrder==null||finishedOrder.size()==0)
        {
            return;
        }

        CopyOnWriteArrayList<Integer> oldSequence=chromosome.getOperationSequencing();
        CopyOnWriteArrayList<Integer> finalSequence = new CopyOnWriteArrayList<>();
        // 初始化两个结果数组
        CopyOnWriteArrayList<Integer> pfSequence = new CopyOnWriteArrayList<>(); // 成品工序
        Map<Integer, List<Integer>> sfSequence = new HashMap<>(); // 半成品工序

        // 遍历原数组分类
        for (int num : oldSequence) {
            if (finishedOrder.contains(num)) {
                pfSequence.add(num);
            } else {
                if(sfSequence.containsKey(num))
                {
                    sfSequence.get(num).add(num);
                }else {
                    sfSequence.computeIfAbsent(num, k -> new ArrayList<>()).add(num);
                }
            }
        }


        Map<Integer, Integer> orderProcessCounter=new HashMap<>();
        for (int num : pfSequence) {
            int scheduledCount=1;
            if(orderProcessCounter.containsKey(num))
            {
                scheduledCount = orderProcessCounter.get(num)+1;
            }
            int scheduledCount1=scheduledCount;

            List<Entry> operations=  entrysBygroupId.get(num);
            Entry entry=operations.stream()
                    .filter(t->t.getSequence()==scheduledCount1)
                    .findFirst().orElse(null);
            // 找不到当前成品工序时跳过，避免重建排序时空指针。
            if (entry == null) {
                continue;
            }
            int ordertime=orderDueDate.get(entry.getGroupId());
            if(isJit) {

                if(ordertime>0) {
                    entry.setSchedulingMode(Entry.SchedulingMode.BACKWARD.name());
                }else {
                    entry.setSchedulingMode(Entry.SchedulingMode.FORWARD.name());

                }

            }else {
                entry.setSchedulingMode(Entry.SchedulingMode.FORWARD.name());
            }
            if(entry!=null&&entry.getDependentOnOrderIds().size()>0)
            {
                if(isJit&& ordertime>0) {
                    finalSequence.add(num);
                }
                for (int order : entry.getDependentOnOrderIds()) {

                    // 依赖的半成品订单可能不在旧排序里，缺失时跳过，避免空指针。
                    List<Integer> childSequence = sfSequence.get(order);
                    if (childSequence == null || childSequence.isEmpty()) {
                        continue;
                    }
                    for (int num1 : childSequence){
                        InsertSimSequence(orderProcessCounter,num1,finalSequence,sfSequence,entrysBygroupId);
                    }
                }
                if(!isJit|| ordertime<=0) {
                    finalSequence.add(num);
                }
            }else {

                finalSequence.add(num);
            }
            orderProcessCounter.put(num, scheduledCount);
        }
        chromosome.setOperationSequencing(finalSequence);
    }

    private void InsertSimSequence(Map<Integer, Integer> orderProcessCounter,int orderid,List<Integer> finalSequence,Map<Integer, List<Integer>> sfSequence,Map<Integer, List<Entry>> entrysBygroupId)
    {
        Random rnd = new Random();
        int scheduledCount=1;
        if(orderProcessCounter.containsKey(orderid))
        {
            scheduledCount = orderProcessCounter.get(orderid)+1;
        }
        int scheduledCount1=scheduledCount;
        Entry entry=entrysBygroupId.get(orderid).stream()
                .filter(t->t.getSequence()==scheduledCount1)
                .findFirst().orElse(null);
        // 找不到下一道工序说明该订单已插够次数，不能再写入 finalSequence。
        if (entry == null) {
            return;
        }
        entry.setSchedulingMode(Entry.SchedulingMode.BACKWARD.name());
        if(entry!=null&&entry.getDependentOnOrderIds().size()>0) {

            for (int order : entry.getDependentOnOrderIds()) {

                // 依赖的半成品订单可能不在旧排序里，缺失时跳过，避免空指针。
                List<Integer> childSequence = sfSequence.get(order);
                if (childSequence == null || childSequence.isEmpty()) {
                    continue;
                }
                for (int num1 : childSequence) {
                    InsertSimSequence(orderProcessCounter,num1,finalSequence,sfSequence,entrysBygroupId);
                }
            }
            finalSequence.add(orderid);
        }else {
            int insertPos = Math.max(0, finalSequence.size());

            // int insertPos = Math.max(0, finalSequence.size() - rnd.nextInt(2));
            finalSequence.add(insertPos,orderid);
        }
        orderProcessCounter.put(orderid, scheduledCount);
    }

    /**
     * 按真实工序数规整工序排序序列。
     * operationSequencing 存的是订单 groupId，每出现一次代表调度该订单的下一道工序。
     * CreateNewOpSequence 可能重新插入半成品订单，需防止同一订单出现次数超过实际工序数。
     */
    private void normalizeOperationSequencing(Chromosome chromosome) {
        List<Entry> allOperations = chromosome.getAllOperations();
        List<Integer> operationSequencing = chromosome.getOperationSequencing();
        if (allOperations == null || operationSequencing == null) {
            return;
        }

        Map<Integer, Long> expectedCounts = allOperations.stream()
                .collect(Collectors.groupingBy(Entry::getGroupId, Collectors.counting()));
        Map<Integer, Integer> actualCounts = new HashMap<>();
        CopyOnWriteArrayList<Integer> normalized = new CopyOnWriteArrayList<>();

        // 先保留原序列中的合法次数，超过真实工序数的重复 groupId 丢弃。
        for (Integer groupId : operationSequencing) {
            if (groupId == null) {
                continue;
            }
            long expected = expectedCounts.getOrDefault(groupId, 0L);
            int actual = actualCounts.getOrDefault(groupId, 0);
            if (actual < expected) {
                normalized.add(groupId);
                actualCounts.put(groupId, actual + 1);
            }
        }

        // 如果序列缺少某些工序，再按 groupId + sequence 补齐，保证每道工序都有一次调度机会。
        allOperations.stream()
                .sorted(Comparator.comparing(Entry::getGroupId).thenComparing(Entry::getSequence))
                .forEach(op -> {
                    int groupId = op.getGroupId();
                    long expected = expectedCounts.getOrDefault(groupId, 0L);
                    int actual = actualCounts.getOrDefault(groupId, 0);
                    if (actual < expected) {
                        normalized.add(groupId);
                        actualCounts.put(groupId, actual + 1);
                    }
                });

        chromosome.setOperationSequencing(normalized);
    }

    public void decode(Chromosome chromosome,boolean isParallel) {

//
//        // 根据工序数量和CPU核心数决定是否使用内部并行
        if (isParallel) {
            // 使用设备并行处理
            //  FileHelper.writeLogFile("使用并行处理 _s");
            parallelDecodeByMachine(chromosome);
            //  FileHelper.writeLogFile("使用并行处理 _e");
        }
        else {
            // 使用串行处理
//            FileHelper.writeLogFile("使用串行处理 _s");
            serialDecode(chromosome);
//            FileHelper.writeLogFile("使用串行处理 _e");

        }
    }
    /**
     * 染色体解码为调度方案
     */
    public void decode(Chromosome chromosome, boolean isParallel, boolean rebuildStructure) {
        boolean previousFlag = this.rebuildStructureForCurrentDecode;
        this.rebuildStructureForCurrentDecode = rebuildStructure;
        try {
            decode(chromosome, isParallel);
        } finally {
            this.rebuildStructureForCurrentDecode = previousFlag;
        }
    }

    public void serialDecode(Chromosome chromosome) {
        long decodeStart = System.nanoTime();
        chromosome.setScenarioID(sceneId);
        boolean isJit=_globalParam.isJit();



        if (rebuildStructureForCurrentDecode&&_globalParam.isIsCheckSf()) {
            long t1 = System.nanoTime();
            //创建半成品订单
            materialRequirementService.buildMultiLevelRequirementNetwork(chromosome, sceneId, baseTime,_globalParam);
//            FileHelper.writeLogFile("[PERF] serialDecode buildMultiLevelRequirementNetwork 耗时=" + fmtMs(System.nanoTime() - t1));
        }
        List<Entry> allOperations=chromosome.getAllOperations();

        Map<Integer, Integer> orderProcessCounter = new HashMap<>();
        Map<Integer, Integer> orderLastEndTime = new HashMap<>();


        //工序对应的排产结果
        Map<Integer, GAScheduleResult> scheduleIndexById = new ConcurrentHashMap<>();

        Map<Integer, Entry> entryIndexById = new HashMap<>();
        Map<Integer, List<Entry>> entrysBygroupId = new HashMap<>();
        for (Entry op : allOperations) {
            int groupId = op.getGroupId();
            orderProcessCounter.putIfAbsent(groupId, 0);
            orderLastEndTime.putIfAbsent(groupId, 0);
            //工序
            entryIndexById.put(op.getId(),op);
            //订单下全部工序
            entrysBygroupId.computeIfAbsent(groupId, k -> new ArrayList<>()).add(op);
            //scheduleIndexById.put(op.getId(),null);

        }
        Map<Integer, Integer> orderDueDate = new HashMap<>();
        Map<Integer, AbstractMap.SimpleEntry<Boolean, Integer>> orderSchedulingInfo = new HashMap<>();

        for (Order order : chromosome.getOrders()) {

            int end = (int) ChronoUnit.SECONDS.between(baseTime, order.getDueDate());
            orderDueDate.putIfAbsent(order.getId(), end);
            //存储锚点时间
            if(isJit)
            {
                if(end>0)
                {
                    orderSchedulingInfo.put(order.getId(), new AbstractMap.SimpleEntry<>(true, end));

                }else {
                    orderSchedulingInfo.put(order.getId(), new AbstractMap.SimpleEntry<>(false, 0));

                }

            }else {
                orderSchedulingInfo.put(order.getId(), new AbstractMap.SimpleEntry<>(false, 0));

            }

        }

        if(rebuildStructureForCurrentDecode && _globalParam.isIsCheckSf()) {
            long t1 = System.nanoTime();
            int isnew=   generateGlobalOpList(chromosome);
//            FileHelper.writeLogFile("[PERF] serialDecode generateGlobalOpList 耗时=" + fmtMs(System.nanoTime() - t1) + ", isnew=" + isnew);

            if(isnew==1) {
                long t2 = System.nanoTime();
                CreateNewOpSequence(chromosome,orderDueDate,entrysBygroupId,isJit);
                // CreateNewOpSequence 会重建半成品插入顺序，生成后再规整一次，避免重复调度同一订单。
                normalizeOperationSequencing(chromosome);
//                FileHelper.writeLogFile("[PERF] serialDecode CreateNewOpSequence 耗时=" + fmtMs(System.nanoTime() - t2));
            }
        }

        List<GlobalOperationInfo> globalOpList=chromosome.getGlobalOpList();
        allOperations.forEach(t -> t.setLatestCompletionTime(null));




        Map<Long, Machine> machineIdMap = chromosome.getMachines().stream()
                .collect(Collectors.toMap(Machine::getId, m -> m));



        // 验证：MachineSelection长度必须与全局工序数一致
        if (chromosome.getMachineSelection().size() != globalOpList.size()) {
            throw new IllegalArgumentException(String.format(
                    "MachineSelection长度（%d）与全局工序数（%d）不匹配！",
                    chromosome.getMachineSelection().size(), globalOpList.size()));
        }

        // 步骤1：生成“工序→机器/加工时间”映射
        List<OpMachine> opMachineMap = new ArrayList<>();
        Map<String, OpMachine> opMachineKeyMap = new HashMap<>();

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

            // 从MachineSelection中获取当前工序的机器选择顺序号
            int machineSeq = chromosome.getMachineSelection().get(globalOpId);
            List<MachineOption> optionalMachines = op.getMachineOptions();

            // 验证：机器顺序号必须在可选范围内
            if (machineSeq < 1 || machineSeq > optionalMachines.size()) {
                throw new IllegalStateException(String.format(
                        "全局工序%d（订单%d工序%d）的机器顺序号%d超出范围（1-%d）",
                        globalOpId, groupId, sequence, machineSeq, optionalMachines.size()));
            }

            // 获取选择的设备ID和加工时间
            MachineOption selectedMachine = optionalMachines.get(machineSeq - 1);
            OpMachine opMachine=new OpMachine();
            opMachine.setGroupId(groupId);
            opMachine.setSequence(sequence);
            opMachine.setMachineId(selectedMachine.getMachineId());
            opMachine.setProcessingTime(selectedMachine.getProcessingTime());
            opMachine.setRuntime(selectedMachine.getRuntime());
            opMachine.setSingleOut(selectedMachine.getSingleOut());

            opMachineMap.add(opMachine);
            String key = opMachine.getGroupId() + "_" + opMachine.getSequence();
            opMachineKeyMap.put(key, opMachine);
        }





        Set<Integer> semiFinishedOrderIds=new HashSet<>();
        if(isJit)
        {
            // 半成品订单ID集合
            semiFinishedOrderIds = chromosome.getOrders().stream()
                    .filter(Order::isNewSfCreate).map(Order::getId).collect(Collectors.toSet());

        }
            for (Map.Entry<Integer, List<Entry>> entry : entrysBygroupId.entrySet()) {
                int groupId = entry.getKey();
                Entry firstOp = entry.getValue().get(0);
                if(isJit) {
                    if (Entry.SchedulingMode.BACKWARD.name().equals(
                            firstOp.getSchedulingMode()) && semiFinishedOrderIds.contains(groupId)) {
                        orderSchedulingInfo.put(groupId,
                                new AbstractMap.SimpleEntry<>(true, 0));
                    }
                }else {
                    if (Entry.SchedulingMode.BACKWARD.name().equals(
                            firstOp.getSchedulingMode())) {
                        orderSchedulingInfo.put(groupId,
                                new AbstractMap.SimpleEntry<>(true, 0));
                    }
                }
            }



//        Map<Long, String> machineState = chromosome.getMachines().stream()
//                .collect(Collectors.toMap(Machine::getId, m -> ""));

        //  List<Entry> allScheduledOps = new ArrayList<>();
        // 缓存机器任务
        Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache = new HashMap<>();
        // 记录已经整单转正排的订单，避免倒排序列后续再次进入同一个 groupId。
        Set<Integer> forwardFallbackOrderIds = new HashSet<>();

        // 混合排程：半成品正排后需要重排的成品订单
        Set<Integer> reForwardFinishedOrderIds = new HashSet<>();
        // 延迟重排映射：半成品ID → 关联成品ID集合（等半成品全部排完后再处理）
        Map<Integer, Set<Integer>> pendingReForwardMap = new HashMap<>();
        // 倒排订单：延迟扣库存，等整单排完后按正序统一扣
        Set<Integer> jitDeferredBomOrderIds = new HashSet<>();

        Map<Integer, Order> orders = chromosome.getOrders().stream()
                .collect(Collectors.toMap(
                        Order::getId,
                        // 2. Value映射：Material → Material
                        order -> order
                ));


        int opCount = 0;
        long slowOpThresholdNs = 500_000_000L; // 500ms


Map<Integer, Integer> targetGroupEnd=new HashMap<>();
        for (int groupId : chromosome.getOperationSequencing()) {
            int scheduledCount = orderProcessCounter.get(groupId);

            if(groupId==15||groupId==16)
            {
                int i=0;
            }

            List<Entry> orderOps=new ArrayList<>();

            boolean orderIsJit=orderDueDate.get(groupId)>0;


            AbstractMap.SimpleEntry<Boolean, Integer> schedInfo = orderSchedulingInfo.get(groupId);

            orderIsJit = schedInfo != null && schedInfo.getKey();
            // 半成品倒排失败后，关联成品强制正排
            if (reForwardFinishedOrderIds.contains(groupId)) {
                orderIsJit = false;
                schedInfo = new AbstractMap.SimpleEntry<>(false, 0);
            }
            int orderAnchor = schedInfo != null ? schedInfo.getValue() : 0;

            // 半成品订单首次处理时，延迟计算锚点：沿依赖链找到根成品工序并正推
            if (orderIsJit && orderAnchor == 0) {


                if (semiFinishedOrderIds.contains(groupId)) {
                  Order order=  orders.get(groupId);
                    orderAnchor =bom.computeHybridSemiAnchor(this,groupId, entrysBygroupId,
                            opMachineKeyMap, chromosome, scheduleIndexById,
                            machineTasksCache, machineIdMap, entryIndexById,
                            reForwardFinishedOrderIds,_globalParam,order,targetGroupEnd);

                    if (orderAnchor < 0) {
                        orderIsJit = false;
                        orderSchedulingInfo.put(groupId,
                                new AbstractMap.SimpleEntry<>(false, -1));
                        if (!reForwardFinishedOrderIds.isEmpty()) {
                            pendingReForwardMap.put(groupId,
                                    new HashSet<>(reForwardFinishedOrderIds));
                            reForwardFinishedOrderIds.clear();
                        }

                    } else {
                        orderSchedulingInfo.put(groupId,
                                new AbstractMap.SimpleEntry<>(true, orderAnchor));
                    }
                } else {
                    orderAnchor = bom.computeSemiFinishedAnchor(this, groupId, entrysBygroupId,
                            opMachineKeyMap, chromosome,
                            scheduleIndexById, machineTasksCache, machineIdMap, entryIndexById,_globalParam.isIsCheckMp(),targetGroupEnd);
                    if (orderAnchor < 0) {
                        orderIsJit = false;
                        orderSchedulingInfo.put(groupId,
                                new AbstractMap.SimpleEntry<>(false, -1));
                    } else {
                        orderSchedulingInfo.put(groupId,
                                new AbstractMap.SimpleEntry<>(true, orderAnchor));
                    }
                }

            }



            if(orderIsJit)
            {

                    jitDeferredBomOrderIds.add(groupId);


                orderOps = entrysBygroupId.get(groupId).stream()
                        .sorted(Comparator.comparing(Entry::getSequence).reversed())
                        .collect(Collectors.toList());

            }else {
                 orderOps = entrysBygroupId.get(groupId).stream()
                        .sorted(Comparator.comparing(Entry::getSequence))
                        .collect(Collectors.toList());

            }



            if (scheduledCount >= orderOps.size()) {
                if (forwardFallbackOrderIds.contains(groupId)) {
                    continue;
                }
                throw new IllegalStateException(String.format(
                        "订单%d的工序已全部调度（共%d道），无需重复处理！",
                        groupId, orderOps.size()));
            }

            Entry currentOp = orderOps.get(scheduledCount);

//FileHelper.writeLogFile("工序："+currentOp.getId());

            int opSequence = currentOp.getSequence();

            GAScheduleResult existingResult = chromosome.getResultOld().stream()
                    .filter(r-> r.getOperationId() == currentOp.getId())
                    .findFirst().orElse(null);
            if(existingResult!=null) {
                if(existingResult.isIsLocked())
                {
                    continue;
                }
            }

            String opMachineKey = groupId + "_" + opSequence;
            OpMachine machineOption = opMachineKeyMap.get(opMachineKey);

            Long machineId = machineOption.getMachineId();
            double processTime = machineOption.getProcessingTime();

            long opStart = System.nanoTime();

            boolean opIsJit = orderIsJit
                    ||( Entry.SchedulingMode.BACKWARD.name().equals(
                    currentOp.getSchedulingMode())&&orderAnchor>0);
            int dueDateForOp = opIsJit ? orderAnchor
                    : (schedInfo != null ? schedInfo.getValue() : 0);

            OperationScheduleResult operationResult = processOperationSchedule(currentOp, machineId, processTime,
                    machineOption, chromosome, machineIdMap, machineTasksCache, entryIndexById,
                    scheduleIndexById, dueDateForOp, 0,true, opIsJit);
            if (operationResult.isForwardFallbackRequired()) {

                // 倒排失败时只修复当前工序及其后道已排工序。
                // 例如倒排顺序 3->2->1，2 放不下时撤回 2、3，再按 2->3 放到各自设备最后任务之后。
                List<Integer> removeOp = clearOrderSchedulingFromSequence(chromosome, groupId, opSequence,
                        entrysBygroupId, machineTasksCache, scheduleIndexById,entryIndexById);

                int repairStartTime = operationResult.getStartTime();
                int forwardEndTime = scheduleOrderForwardFallback(groupId, removeOp, repairStartTime, chromosome,entrysBygroupId, machineIdMap, machineTasksCache,
                        entryIndexById, scheduleIndexById, opMachineKeyMap);
                orderProcessCounter.put(groupId, scheduledCount + 1);
                orderLastEndTime.put(groupId, forwardEndTime);
                if (orderProcessCounter.get(groupId) >= entrysBygroupId.get(groupId).size()) {
                    forwardFallbackOrderIds.add(groupId);
                }
                //如果是半成品
                if (semiFinishedOrderIds.contains(groupId)) {
                    Set<Integer> fallbackFinishedIds = new HashSet<>();
                    List<Integer> targetFinishedOpIds = currentOp.getTargetFinishedOperationId();
                    if (targetFinishedOpIds != null && !targetFinishedOpIds.isEmpty()) {
                        for (Integer targetOpId : targetFinishedOpIds) {
                            Entry finishedOp = entryIndexById.get(targetOpId);
                            if (finishedOp != null) {
                                fallbackFinishedIds.add(finishedOp.getGroupId());
                            }
                        }
                    }
                    reForwardFinishedOrders(groupId,forwardEndTime, fallbackFinishedIds,
                            chromosome, machineTasksCache, scheduleIndexById,
                            machineIdMap, entryIndexById, opMachineKeyMap,
                            entrysBygroupId, orderProcessCounter, orderLastEndTime,
                            forwardFallbackOrderIds, orderSchedulingInfo);
                }
                opCount += removeOp.size();
                continue;
            }
            int actualEndTime = operationResult.getEndTime();
            long opElapsed = System.nanoTime() - opStart;
            opCount++;


            if(currentOp.getId()==60)
            {
                int k=0;
            }

            orderProcessCounter.put(groupId, orderProcessCounter.get(groupId) + 1);
            orderLastEndTime.put(groupId, actualEndTime);


            if (isJit&& orderProcessCounter.get(groupId) >= entrysBygroupId.get(groupId).size()) {

                List<Entry> orderOpsBySeq = entrysBygroupId.get(groupId).stream()
                        .sorted(Comparator.comparingInt(Entry::getSequence))
                        .collect(Collectors.toList());
                boolean bomFailed = false;
                int failedSeq = -1;
                int failedBomTime = 0;
                for (Entry op : orderOpsBySeq) {
                    GAScheduleResult result = scheduleIndexById.get(op.getId());
                    if (result == null||!result.isIsJit()) continue;
                    int bomTime = getOperationBOMTime(op, chromosome, result.getStartTime(), 3,_globalParam.isIsCheckMp());
                    if (bomTime <= result.getStartTime()) {
                        EditOperationBOMTime(op, chromosome, result.getStartTime(),
                                machineTasksCache, entryIndexById,
                                scheduleIndexById);
                    } else {
                        bomFailed = true;
                        failedSeq = op.getSequence();
                        failedBomTime = bomTime;
                        break;
                    }
                }
                if (bomFailed) {
                    int finalFailedSeq = failedSeq;
                    Set<Integer> keepOpIds = orderOpsBySeq.stream()
                            .filter(op -> op.getSequence() < finalFailedSeq)
                            .map(Entry::getId)
                            .collect(Collectors.toSet());
                    FileHelper.writeLogFile("[BomFallback] 订单" + groupId
                            + "工序" + failedSeq + "物料不足(bomTime="
                            + failedBomTime + " > startTime)，从该工序开始正排");
                    List<Integer> removeOp =   clearOrderSchedulingForForwardFallback(chromosome, groupId,
                            machineTasksCache, scheduleIndexById,entryIndexById, keepOpIds);
                    int forwardEndTime = scheduleOrderForwardFallback(groupId,removeOp,failedBomTime,
                            chromosome,entrysBygroupId, machineIdMap, machineTasksCache,
                    entryIndexById, scheduleIndexById, opMachineKeyMap);
                    forwardFallbackOrderIds.add(groupId);
                    orderSchedulingInfo.put(groupId,
                            new AbstractMap.SimpleEntry<>(false, 0));
                    orderLastEndTime.put(groupId, forwardEndTime);
                }

                if (semiFinishedOrderIds.contains(groupId)) {
                    Set<Integer> pendingFinishedIds = pendingReForwardMap.remove(groupId);
                    if (pendingFinishedIds != null && !pendingFinishedIds.isEmpty()) {
                        int semiEndTime = orderLastEndTime.get(groupId);
//                        FileHelper.writeLogFile("[ReForward] 半成品" + groupId
//                                + "全部排完(结束时间=" + semiEndTime + ")，重新正排关联成品"
//                                + pendingFinishedIds);
                        reForwardFinishedOrders(groupId,semiEndTime, pendingFinishedIds,
                                chromosome, machineTasksCache, scheduleIndexById,
                                machineIdMap, entryIndexById, opMachineKeyMap,
                                entrysBygroupId, orderProcessCounter, orderLastEndTime,
                                forwardFallbackOrderIds, orderSchedulingInfo);
                    }
                }
            }




        }
        if(chromosome.getReOrderids()!=null&&chromosome.getReOrderids().size()>0) {
            chromosome.getOperationSequencing().removeIf(t -> chromosome.getReOrderids().contains(t));
        }

        long calcStart = System.nanoTime();
        calculateScheduleResult(chromosome);





//        FileHelper.writeLogFile("[PERF] serialDecode calculateScheduleResult 耗时=" + fmtMs(System.nanoTime() - calcStart));
//        FileHelper.writeLogFile("[PERF] serialDecode 总耗时=" + fmtMs(System.nanoTime() - decodeStart) + ", 工序数=" + opCount + ", 全局工序数=" + globalOpList.size());
    }


    public void parallelDecodeByMachine(Chromosome chromosome) {
        if (rebuildStructureForCurrentDecode) {
            //创建半成品订单
            materialRequirementService.buildMultiLevelRequirementNetwork(chromosome, sceneId, baseTime,_globalParam);
        }

        if(rebuildStructureForCurrentDecode && _globalParam.isIsCheckSf()) {
            int isnew=   generateGlobalOpList(chromosome);

            if(isnew==1) {
                CreateNewOpSequence(chromosome,null,null, _globalParam.isJit());
                // CreateNewOpSequence 会重建半成品插入顺序，生成后再规整一次，避免重复调度同一订单。
                normalizeOperationSequencing(chromosome);
            }
        }

        // 1. 获取工序处理顺序
        List<Integer> operationSequencing = chromosome.getOperationSequencing();

        List<GlobalOperationInfo> globalOpList = chromosome.getGlobalOpList();
        List<Entry> allOperations = chromosome.getAllOperations();


        // 2. 构建工序依赖图
        Map<Integer, List<Integer>> dependencyGraph = buildDependencyGraph(chromosome);
        Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache = new HashMap<>();
        Map<Long, Machine> machineIdMap = chromosome.getMachines().stream()
                .collect(Collectors.toMap(Machine::getId, m -> m));

        // 生成“工序→机器/加工时间”映射
        List<OpMachine> opMachineMap = new ArrayList<>();
        Map<String, OpMachine> opMachineKeyMap = new HashMap<>();

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

            // 从MachineSelection中获取当前工序的机器选择顺序号
            int machineSeq = chromosome.getMachineSelection().get(globalOpId);
            List<MachineOption> optionalMachines = op.getMachineOptions();

            // 验证：机器顺序号必须在可选范围内
            if (machineSeq < 1 || machineSeq > optionalMachines.size()) {
                throw new IllegalStateException(String.format(
                        "全局工序%d（订单%d工序%d）的机器顺序号%d超出范围（1-%d）",
                        globalOpId, groupId, sequence, machineSeq, optionalMachines.size()));
            }

            // 获取选择的设备ID和加工时间
            MachineOption selectedMachine = optionalMachines.get(machineSeq - 1);
            OpMachine opMachine = new OpMachine();
            opMachine.setGroupId(groupId);
            opMachine.setSequence(sequence);
            opMachine.setMachineId(selectedMachine.getMachineId());
            opMachine.setProcessingTime(selectedMachine.getProcessingTime());
            opMachine.setRuntime(selectedMachine.getRuntime());
            opMachine.setSingleOut(selectedMachine.getSingleOut());

            opMachineMap.add(opMachine);
            String key = opMachine.getGroupId() + "_" + opMachine.getSequence();
            opMachineKeyMap.put(key, opMachine);
        }

        // 初始化订单处理计数器
        Map<Integer, Integer> orderProcessCounter = new HashMap<>();

        Map<Integer, Entry> entryIndexById = new HashMap<>();
        Map<Integer, List<Entry>> entrysBygroupId = new HashMap<>();
        Map<Integer, GAScheduleResult> scheduleIndexById= new ConcurrentHashMap<>();
        Map<Integer, Integer> orderDueDate = new HashMap<>();
        for (Order order : chromosome.getOrders()) {

            int end = (int) ChronoUnit.SECONDS.between(baseTime, order.getDueDate());
            orderDueDate.putIfAbsent(order.getId(), end);
        }

        for (Entry op : allOperations) {
            int groupId = op.getGroupId();
            orderProcessCounter.putIfAbsent(groupId, 0);

            entryIndexById.put(op.getId(),op);
            entrysBygroupId.computeIfAbsent(groupId, k -> new ArrayList<>()).add(op);
        }
        Map<Long, List<Entry>> machineToOpsMap = new HashMap<>();
        //按照 OperationSequencing 顺序生成 machineToOpsMap
        for (int groupId : operationSequencing) {
            int scheduledCount = orderProcessCounter.get(groupId);
            List<Entry> orderOps = allOperations.stream()
                    .filter(t -> t.getGroupId() == groupId)
                    .sorted(Comparator.comparing(Entry::getSequence))
                    .collect(Collectors.toList());

            if (scheduledCount >= orderOps.size()) {
                throw new IllegalStateException(String.format(
                        "订单%d的工序已全部调度（共%d道），无需重复处理！",
                        groupId, orderOps.size()));
            }

            Entry currentOp = orderOps.get(scheduledCount);

            String opMachineKey = groupId + "_" + currentOp.getSequence();
            OpMachine machineOption = opMachineKeyMap.get(opMachineKey);

            Long machineId = machineOption.getMachineId();
            machineToOpsMap.computeIfAbsent(machineId, k -> new ArrayList<>()).add(currentOp);
            orderProcessCounter.put(groupId, orderProcessCounter.get(groupId) + 1);

        }
// 6. 按照每个设备队列中第一个工序的 sequence 递增顺序排序
        List<Map.Entry<Long, List<Entry>>> sortedMachineEntries = new ArrayList<>(machineToOpsMap.entrySet());
        sortedMachineEntries.sort((e1, e2) -> {
            List<Entry> ops1 = e1.getValue();
            List<Entry> ops2 = e2.getValue();

            if (ops1.isEmpty() && ops2.isEmpty()) {
                return 0;
            }
            if (ops1.isEmpty()) {
                return 1;
            }
            if (ops2.isEmpty()) {
                return -1;
            }

            int sequence1 = ops1.get(0).getSequence();
            int sequence2 = ops2.get(0).getSequence();
            int sequenceCompare = Integer.compare(sequence1, sequence2);

            if (sequenceCompare == 0) {
                // sequence 相同的情况下，按照设备下 Entry 的数量递增排序
                return Integer.compare(ops1.size(), ops2.size());
            } else {
                return sequenceCompare;
            }
        });


        // 7. 初始化同步机制
//        Map<Integer, CompletableFuture<Void>> opFutures = new ConcurrentHashMap<>();
//        Map<Long, CompletableFuture<Void>> machineFutures = new ConcurrentHashMap<>();
//
//        // 8. 并行处理每个设备的工序（按照排序后的顺序）
//        List<CompletableFuture<Void>> allMachineFutures = new ArrayList<>();
//
//        for (Map.Entry<Long, List<Entry>> entry : sortedMachineEntries) {
//            final Long machineId = entry.getKey();
//            final List<Entry> ops = entry.getValue();
//            FileHelper.writeLogFile("使用并行处理 _s---"+machineId);
//            CompletableFuture<Void> machineFuture = CompletableFuture.runAsync(() -> {
//                // 顺序处理设备上的工序
//                int i=0;
//                for (Entry op : ops) {
//                    int opId = op.getId();
//                    String opMachineKey = op.getGroupId() + "_" + op.getSequence();
//                    OpMachine machineOption = opMachineKeyMap.get(opMachineKey);
//
//
//                    double processTime = machineOption.getProcessingTime();
//                    // 获取当前工序的依赖
//                    List<Integer> dependencies = dependencyGraph.getOrDefault(opId, Collections.emptyList());
//                    // 等待所有依赖完成
//                    List<CompletableFuture<Void>> dependencyFutures = dependencies.stream()
//                            .map(opFutures::get)
//                            .filter(Objects::nonNull)
//                            .collect(Collectors.toList());
//
//                    // 等待设备上一个工序完成
//                    CompletableFuture<Void> prevMachineFuture = machineFutures.getOrDefault(machineId, CompletableFuture.completedFuture(null));
//
//                    // 合并所有依赖
//                    List<CompletableFuture<Void>> allDependencies = new ArrayList<>(dependencyFutures);
//                    allDependencies.add(prevMachineFuture);
//                    if(machineId==2341) {
//                        FileHelper.writeLogFile("使用并行处理 ---" + machineId + "----" + i);
//                    }
//                    // 创建当前工序的处理任务
//                    CompletableFuture<Void> currentFuture = CompletableFuture.allOf(allDependencies.toArray(new CompletableFuture[0]))
//                            .thenRun(() -> {
//                                // 处理当前工序
//                                int actualEndTime =  processOperation(op,machineId,processTime,machineOption,chromosome,machineIdMap,machineTasksCache);
//
//                            });
//
//                    // 保存当前工序的Future
//                    opFutures.put(opId, currentFuture);
//                    // 更新设备的Future
//                    machineFutures.put(machineId, currentFuture);
//
//                    // 等待当前工序完成
//                    try {
//                        currentFuture.get();
//                    } catch (Exception e) {
//                        e.printStackTrace();
//                    }
//                    i++;
//                    if(i==ops.size())
//                    {
//                        FileHelper.writeLogFile("使用并行处理 _e---"+machineId);
//
//                    }
//                }
//            });
//
//            allMachineFutures.add(machineFuture);
//        }
// 7. 改进的并行处理：只对工序少的设备并行，工序多的设备串行
        Map<Integer, Boolean> opCompleted = new HashMap<>();
        final Object lock = new Object();

        List<Thread> threads = new ArrayList<>();
        for (Map.Entry<Long, List<Entry>> entry : sortedMachineEntries) {
            final Long machineId = entry.getKey();
            final List<Entry> ops = entry.getValue();

            // 工序超过500的设备直接在主线程串行处理
            if (ops.size() > 500) {
                //   FileHelper.writeLogFile("设备 " + machineId + " 有 " + ops.size() + " 个工序，直接串行处理");
                processMachineOps(chromosome, machineId, ops, dependencyGraph, opCompleted, lock, opMachineKeyMap, machineIdMap, machineTasksCache, entryIndexById,scheduleIndexById,orderDueDate);
            } else {
                // 工序少的设备创建线程处理
                Thread thread = new Thread(() -> {
                    processMachineOps(chromosome, machineId, ops, dependencyGraph, opCompleted, lock, opMachineKeyMap, machineIdMap, machineTasksCache, entryIndexById,scheduleIndexById,orderDueDate);
                });
                thread.start();
                threads.add(thread);
            }
        }

        // 等待所有线程完成
        for (Thread thread : threads) {
            try {
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        // 9. 等待所有设备处理完成
        //  CompletableFuture.allOf(allMachineFutures.toArray(new CompletableFuture[0])).join();

        if (chromosome.getReOrderids() != null && chromosome.getReOrderids().size() > 0) {
            chromosome.getOperationSequencing().removeIf(t -> chromosome.getReOrderids().contains(t));
        }

        calculateScheduleResult(chromosome);
    }

    /**
     * 处理单个设备的工序
     */
    private void processMachineOps(Chromosome chromosome, Long machineId, List<Entry> ops,
                                   Map<Integer, List<Integer>> dependencyGraph,
                                   Map<Integer, Boolean> opCompleted, Object lock,Map<String, OpMachine> opMachineKeyMap,Map<Long, Machine> machineIdMap,Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,Map<Integer, Entry> entryIndexById,Map<Integer, GAScheduleResult> scheduleIndexById,Map<Integer, Integer> orderDueDate) {
        //long machineStartTime = System.currentTimeMillis();

        for (int i = 0; i < ops.size(); i++) {
            Entry op = ops.get(i);
            int opId = op.getId();
            long opStartTime = System.currentTimeMillis();

            // 获取当前工序的依赖
            List<Integer> dependencies = dependencyGraph.getOrDefault(opId, Collections.emptyList());

            // 等待所有依赖完成
            boolean allDependenciesCompleted;
            synchronized (lock) {
                allDependenciesCompleted = true;
                for (int depId : dependencies) {
                    if (!opCompleted.getOrDefault(depId, false)) {
                        allDependenciesCompleted = false;
                        break;
                    }
                }
            }

            if (!allDependenciesCompleted) {
                // 需要等待依赖
                waitForDependencies(dependencies, opCompleted, lock);
            }

            String opMachineKey = op.getGroupId() + "_" + op.getSequence();
            OpMachine machineOption = opMachineKeyMap.get(opMachineKey);


            double processTime = machineOption.getProcessingTime();

            int orderDueDate1=orderDueDate.get(op.getGroupId());
            // 处理当前工序
            //   long processStartTime = System.currentTimeMillis();
            int actualEndTime =  processOperation(op,machineId,processTime,machineOption,chromosome,machineIdMap,machineTasksCache, entryIndexById,scheduleIndexById,orderDueDate1,true,false);

            //   long processEndTime = System.currentTimeMillis();

            // 标记工序完成
            synchronized (lock) {
                opCompleted.put(opId, true);
            }

            //    long opEndTime = System.currentTimeMillis();
//            if (i % 100 == 0 || i == ops.size() - 1) {
//                FileHelper.writeLogFile("设备 " + machineId + " 工序 " + i + "/" + ops.size() +
//                        " 完成，总耗时：" + (opEndTime - machineStartTime) + "ms，本工序耗时：" + (opEndTime - opStartTime) + "ms");
//            }
        }

//        long machineEndTime = System.currentTimeMillis();
//        FileHelper.writeLogFile("设备 " + machineId + " 处理完成，总工序：" + ops.size() +
//                "，总耗时：" + (machineEndTime - machineStartTime) + "ms");
    }

    /**
     * 等待依赖工序完成
     */
    private void waitForDependencies(List<Integer> dependencies, Map<Integer, Boolean> opCompleted, Object lock) {
        while (true) {
            boolean allCompleted;
            synchronized (lock) {
                allCompleted = true;
                for (int depId : dependencies) {
                    if (!opCompleted.getOrDefault(depId, false)) {
                        allCompleted = false;
                        break;
                    }
                }
                if (allCompleted) {
                    break;
                }
            }

            // 短暂休眠，避免CPU空转
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                break;
            }
        }
    }

    /**
     * 构建工序依赖图，只考虑通过 getPrevOperationId 定义的依赖关系
     */
    private Map<Integer, List<Integer>> buildDependencyGraph(Chromosome chromosome) {
        Map<Integer, List<Integer>> dependencyGraph = new HashMap<>();

        // 只添加通过 getPrevOperationId 定义的依赖关系
        for (Entry op : chromosome.getAllOperations()) {
            int opId = op.getId();
            List<Integer> dependencies = new ArrayList<>();

            // 添加前序工序依赖（包括订单内和跨订单的依赖）
            for (OperationDependency dep : op.getPrevEntryIds()) {
                dependencies.add(dep.getPrevOperationId());
            }

            dependencyGraph.put(opId, dependencies);
        }

        return dependencyGraph;
    }

    /**
     * 拓扑排序
     */
    private List<Integer> topologicalSort(Map<Integer, List<Integer>> graph, Chromosome chromosome) {
        List<Integer> result = new ArrayList<>();
        Map<Integer, Integer> inDegree = new HashMap<>();

        // 初始化入度
        for (Integer node : graph.keySet()) {
            inDegree.put(node, 0);
        }

        for (List<Integer> dependencies : graph.values()) {
            for (Integer dep : dependencies) {
                inDegree.put(dep, inDegree.getOrDefault(dep, 0) + 1);
            }
        }

        // 获取订单处理顺序
        List<Integer> operationSequencing = chromosome.getOperationSequencing();

        // 构建订单ID到工序ID的映射
        Map<Integer, List<Integer>> orderToOpIdsMap = new HashMap<>();
        for (Entry op : chromosome.getAllOperations()) {
            int groupId = op.getGroupId();
            int opId = op.getId();
            orderToOpIdsMap.computeIfAbsent(groupId, k -> new ArrayList<>()).add(opId);
        }

        // 按照 OperationSequencing 的顺序处理订单
        for (int groupId : operationSequencing) {
            List<Integer> opIds = orderToOpIdsMap.getOrDefault(groupId, Collections.emptyList());

            // 处理当前订单的所有工序
            Queue<Integer> queue = new LinkedList<>();
            for (int opId : opIds) {
                if (inDegree.getOrDefault(opId, 0) == 0) {
                    queue.offer(opId);
                }
            }

            while (!queue.isEmpty()) {
                Integer node = queue.poll();
                result.add(node);

                if (graph.containsKey(node)) {
                    for (Integer neighbor : graph.get(node)) {
                        int newInDegree = inDegree.get(neighbor) - 1;
                        inDegree.put(neighbor, newInDegree);
                        if (newInDegree == 0 && opIds.contains(neighbor)) {
                            queue.offer(neighbor);
                        }
                    }
                }
            }
        }




        return result;
    }
    /**
     * 构建工序ID索引：opId -> Entry（O(1)查找）
     */
    private Map<Integer, Entry> buildOpIdIndex(Chromosome chromosome) {
        Map<Integer, Entry> index = new HashMap<>();
        for (Entry op : chromosome.getAllOperations()) {
            index.put(op.getId(), op);
        }
        return index;
    }
    /**
     * 根据工序ID查找工序
     */
    private Entry findOperationById(Chromosome chromosome, int opId) {
        for (Entry op : chromosome.getAllOperations()) {
            if (op.getId() == opId) {
                return op;
            }
        }
        return null;
    }

    /**
     * 倒排兜底：当前订单已排结果清掉后，按 sequence 从小到大重新正排整单。
     */
    private int scheduleOrderForwardFallback(int groupId,List<Integer> removeOp,int starttime,
                                             Chromosome chromosome,Map<Integer, List<Entry>> entrysBygroupId,
                                             Map<Long, Machine> machineIdMap,
                                             Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,
                                             Map<Integer, Entry> entryIndexById,
                                             Map<Integer, GAScheduleResult> scheduleIndexById,
                                             Map<String, OpMachine> opMachineKeyMap) {
        List<Entry> orderOps =entrysBygroupId.get(groupId);
        List<Entry> operations=new ArrayList<>();
        if(removeOp!=null&&removeOp.size()>0)
        {
            operations=  orderOps.stream()
                    .filter(t ->removeOp.contains(t.getId()))
                    .sorted(Comparator.comparing(Entry::getSequence))
                    .collect(Collectors.toList());
        }else {
            operations=  orderOps.stream()

                    .sorted(Comparator.comparing(Entry::getSequence))
                    .collect(Collectors.toList());
        }


        int finalEndTime = starttime;
        for (Entry currentOp : operations) {
            String opMachineKey = groupId + "_" + currentOp.getSequence();
            OpMachine machineOption = opMachineKeyMap.get(opMachineKey);
            if (machineOption == null) {
                throw new IllegalStateException("未找到正排兜底设备选择，groupId=" + groupId
                        + ", operationId=" + currentOp.getId()
                        + ", sequence=" + currentOp.getSequence());
            }

            int operationStartTime = calcForwardRepairStartTime(currentOp, machineOption, starttime, chromosome,
                    machineIdMap, machineTasksCache, entryIndexById, scheduleIndexById);

            OperationScheduleResult operationResult = processOperationSchedule(currentOp, machineOption.getMachineId(),
                    machineOption.getProcessingTime(), machineOption, chromosome, machineIdMap,
                    machineTasksCache, entryIndexById, scheduleIndexById, 0, operationStartTime,true, false);
            if (operationResult.isForwardFallbackRequired()) {
                throw new IllegalStateException("正排兜底过程中不应再次触发正排兜底，groupId=" + groupId
                        + ", operationId=" + currentOp.getId());
            }
            finalEndTime = operationResult.getEndTime();
        }
        return finalEndTime;
    }

    /**
     * 局部正排修复的起点：不能早于外部指定时间、前序完成时间，也不能插到本设备已有任务中间。
     */
    private int calcForwardRepairStartTime(Entry currentOp,
                                           OpMachine machineOption,
                                           int starttime,
                                           Chromosome chromosome,
                                           Map<Long, Machine> machineIdMap,
                                           Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,
                                           Map<Integer, Entry> entryIndexById,
                                           Map<Integer, GAScheduleResult> scheduleIndexById) {
        int earliestStartTime = starttime;
        Machine targetMachine = machineIdMap.get(machineOption.getMachineId());
        if (targetMachine != null && !currentOp.getPrevEntryIds().isEmpty()) {
            earliestStartTime = CalPrevtime(earliestStartTime, currentOp, chromosome,
                    machineOption.getProcessingTime(), targetMachine, entryIndexById, scheduleIndexById);
        }

        CopyOnWriteArrayList<GAScheduleResult> machineTasks =
                getMachineTasks(machineOption.getMachineId(), chromosome, machineTasksCache);
        GAScheduleResult lastMachineTask = getLastMachineTask(machineTasks);
        if (lastMachineTask != null) {
            earliestStartTime = Math.max(earliestStartTime, lastMachineTask.getEndTime());
        }
        return earliestStartTime;
    }

    private List<Integer> clearOrderSchedulingForForwardFallback(Chromosome chromosome,
                                                        int groupId,
                                                        Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,
                                                        Map<Integer, GAScheduleResult> scheduleIndexById,Map<Integer, Entry> entryIndexById,Set<Integer> keepOpIds) {
        List<GAScheduleResult> resultsToRemove=new ArrayList<>();
      if(keepOpIds!=null&&keepOpIds.size()>0)
      {
           resultsToRemove = chromosome.getResult().stream()
                  .filter(t -> t.getGroupId() == groupId)
                  .filter(t -> !keepOpIds.contains(t.getOperationId()))
                  .collect(Collectors.toList());
      }else {
           resultsToRemove = chromosome.getResult().stream()
                  .filter(t -> t.getGroupId() == groupId)
                  .collect(Collectors.toList());
      }


        List<Integer> operations=new ArrayList<>();

        for (GAScheduleResult result : resultsToRemove) {
            operations.add(result.getOperationId());
            Machine machine = getMachineById(chromosome, result.getMachineId());
            if (machine != null) {
                AddMachineAvailable(machine, result.getGeneDetails());
            }
            chromosome.getResult().remove(result);
            scheduleIndexById.remove(result.getOperationId());

            CopyOnWriteArrayList<GAScheduleResult> machineTasks = machineTasksCache.get(result.getMachineId());
            if (machineTasks != null) {
                machineTasks.removeIf(t -> t.getOperationId() == result.getOperationId());
            }

            Entry op= entryIndexById.get(result.getOperationId());


            Map<String, MaterialDeduction> deductions = readOperationStockDeductions(op);
            if (deductions != null && !deductions.isEmpty()) {
                rollbackOperationStockDeduction(chromosome, deductions);
            }
        }

        machineTasksCache.clear();
        return operations;
    }




    /**
     * 倒排局部失败时，只撤回当前失败工序及其后道已经写入的排程结果。
     * 这样 2 失败只会重排 2、3，1 失败才会重排 1、2、3。
     */
    private List<Integer> clearOrderSchedulingFromSequence(Chromosome chromosome,
                                                           int groupId,
                                                           int failedSequence,
                                                           Map<Integer, List<Entry>> entrysBygroupId,
                                                           Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,
                                                           Map<Integer, GAScheduleResult> scheduleIndexById,Map<Integer, Entry> entryIndexById) {
        Set<Integer> repairOperationIds = entrysBygroupId.getOrDefault(groupId, Collections.emptyList()).stream()
                .filter(op -> op.getSequence() >= failedSequence)
                .map(Entry::getId)
                .collect(Collectors.toCollection(LinkedHashSet::new));

        List<GAScheduleResult> resultsToRemove = chromosome.getResult().stream()
                .filter(result -> repairOperationIds.contains(result.getOperationId()))
                .collect(Collectors.toList());

        for (GAScheduleResult result : resultsToRemove) {

            Entry op= entryIndexById.get(result.getOperationId());


            Map<String, MaterialDeduction> deductions = readOperationStockDeductions(op);
            if (deductions != null && !deductions.isEmpty()) {
                rollbackOperationStockDeduction(chromosome, deductions);
            }
            Machine machine = getMachineById(chromosome, result.getMachineId());
            if (machine != null) {
                AddMachineAvailable(machine, result.getGeneDetails());
            }
            chromosome.getResult().remove(result);
            scheduleIndexById.remove(result.getOperationId());

            CopyOnWriteArrayList<GAScheduleResult> machineTasks = machineTasksCache.get(result.getMachineId());
            if (machineTasks != null) {
                machineTasks.removeIf(t -> t.getOperationId() == result.getOperationId());
            }
        }

        machineTasksCache.clear();
        return new ArrayList<>(repairOperationIds);
    }
    private int processOperation(Entry currentOp, Long machineId, double processTime,
                                 OpMachine machineOption, Chromosome chromosome,
                                 Map<Long, Machine> machineIdMap,
                                 Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,
                                 Map<Integer, Entry> entryIndexById,
                                 Map<Integer, GAScheduleResult> scheduleIndexById,
                                 int orderDueDate, boolean islockMachineTime, boolean isJit) {
        OperationScheduleResult result = processOperationSchedule(currentOp, machineId, processTime, machineOption,
                chromosome, machineIdMap, machineTasksCache, entryIndexById, scheduleIndexById,
                orderDueDate,0, islockMachineTime, isJit);
        return result.getEndTime();
    }

    private OperationScheduleResult processOperationSchedule(Entry currentOp, Long machineId, double processTime,
                                                             OpMachine machineOption, Chromosome chromosome,
                                                             Map<Long, Machine> machineIdMap,
                                                             Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,
                                                             Map<Integer, Entry> entryIndexById,
                                                             Map<Integer, GAScheduleResult> scheduleIndexById,
                                                             int orderDueDate,int starttime, boolean islockMachineTime, boolean isJit) {
        Machine targetMachine = machineIdMap.get(machineId);
        int prevtime = starttime;
        if (isJit) {
            // 倒排边界来自订单交期/锚点；如果存在后道序，则以后道序约束继续往前推。
            prevtime = orderDueDate;
            if (!currentOp.getNextEntryIds().isEmpty()) {
                prevtime = CalNexttime(prevtime, currentOp, chromosome, processTime, targetMachine,
                        entryIndexById, scheduleIndexById);
            }
        } else {
            if (!currentOp.getPrevEntryIds().isEmpty()&&starttime==0) {
                // 正排边界来自前道序完成时间。
                prevtime = CalPrevtime(prevtime, currentOp, chromosome, processTime, targetMachine,
                        entryIndexById, scheduleIndexById);
            }
        }

        int prevendtime = prevtime;
        Machine machine = machineIdMap.get(machineId);
        return processWithSingleMachine(currentOp, machine, processTime, prevtime, machineOption, chromosome,
                false, prevendtime, machineTasksCache, entryIndexById, scheduleIndexById, islockMachineTime, isJit);
    }

    public GAScheduleResult processOperationResult(Entry currentOp, Long machineId, double processTime,
                                                   OpMachine machineOption, Chromosome chromosome,
                                                   Map<Long, Machine> machineIdMap,
                                                   Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,
                                                   Map<Integer, Entry> entryIndexById,
                                                   Map<Integer, GAScheduleResult> scheduleIndexById,
                                                   int orderDueDate, boolean islockMachineTime, boolean isJit) {
        return processOperationSchedule(currentOp, machineId, processTime, machineOption, chromosome, machineIdMap,
                machineTasksCache, entryIndexById, scheduleIndexById, orderDueDate, 0,islockMachineTime, isJit)
                .getScheduleResult();
    }



        private OperationScheduleResult processWithSingleMachine(Entry operation, Machine machine, double  processingTime,

                                         int prevOperationEndTime,OpMachine  machineOption, Chromosome chromosome,boolean calbom,int prevendtime,Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,Map<Integer, Entry> entryIndexById,Map<Integer, GAScheduleResult> scheduleIndexById,boolean islockMachineTime,boolean isJit) {
        long pwsStart = System.nanoTime();
        int processingTimeTotal = 0;
        int earliestStartTime = prevOperationEndTime;
        if (operation.getConstTime() == 1)//常数时间
        {
            processingTimeTotal = (int) Math.ceil(processingTime);
        } else {
            double t = machineOption.getRuntime().doubleValue() / machineOption.getSingleOut().doubleValue() * (operation.getQuantity());
            processingTimeTotal = (int) Math.ceil(t);
        }
        int days = (int) ((processingTimeTotal) / 24 / 3600);
        if (days > 600) {
            throw new RuntimeException("工序总加工时长" + days + "天超出限制");
        }
        if (machine == null || operation.getMachineOptions() == null) {
            return OperationScheduleResult.success(null);
        }

//        MachineOption machineOption= operation.getMachineOptions().stream()
//                .filter(t->t.getMachineId()==machine.getId())
//                .findFirst().orElse(null);

        operation.setSelectMachineID(machine.getId());
        operation.setEquipCode(machine.getCode());
        operation.setEquipName(machine.getName());
        //准备工时
        int setTime = operation.getSetupTime().intValue();
        if (setTime > 0) {
            processingTimeTotal += setTime;//加上准备工时
        }

        //后处理时间
        int teardownTime = operation.getTeardownTime();

        //前处理时间
        int preTime = operation.getPreTime();
        //设置时间平滑 是 不考虑设置时间
        //前处理，是否可以在相同任务前序未完工就开始设置时间，
        // 就是 最早开工时间是否+前处理时间，总的加工工时不考虑前处理
        if (!_globalParam.is_smoothSetup()) {
            // 工序的前处理不能提前，则要在前处理完成后才能开工，所以要在前一工序的结束时间基础上+前处理
            earliestStartTime += preTime;
        }
        int operationId = operation.getId();
        GAScheduleResult existingResult = chromosome.getResultOld().stream().filter(r -> r.getOperationId() == operationId).findFirst().orElse(null);
        if (existingResult != null) {
            earliestStartTime = Math.max(earliestStartTime, existingResult.getDesignatedStartTime());
        }


        if (machine.getCapacityTypeName().equals("Infinite")) {
            int endTime = 0;
            int startTime = 0;
            if (operation.getQuantity() == 0) {
                processingTimeTotal = 0;
            } else {
                processingTimeTotal = (int) Math.ceil(processingTime);
            }
            if (isJit) {
                endTime = earliestStartTime;
                startTime = endTime - processingTimeTotal;

            } else {
                startTime = earliestStartTime;
                endTime = startTime + processingTimeTotal;
            }

            GAScheduleResult result = CreateResult(operation, machine.getId(), startTime, endTime, processingTime, 0, preTime, teardownTime, 0, null, existingResult,machine.getCapacityTypeName(),isJit);

           if(islockMachineTime) {
               chromosome.getResult().add(result);
               machine.setLastGene(result);

               scheduleIndexById.put(operation.getId(), result);
           }
//            if (isJit) {
//                FileHelper.writeLogFile("  半成品    " + operation.getGroupId() + " - " + operation.getSequence() + ",开始时间: " + startTime + ",结束时间: " + endTime + ",处理时间: " + processingTime + ", 后处理: " + teardownTime +
//                        ", 前处理: " + preTime + ", 换型: " + 0 + ", 数量: " + operation.getQuantity() + ", 设备: " + machine.getId() + ", 是否可中断: " + operation.getIsInterrupt());
//
//            }
            return OperationScheduleResult.success(result);
        }


        int setupTime = 0;
        long machineId = machine.getId();
        // 只有存在物料约束（或本次被强制要求重算 BOM）的工序，才需要联立求解“机台何时能排”和“物料何时可用”。
        // targetFinishedOperationId != null 的工序通常由前置成品工序驱动，这里不再额外触发一轮 BOM 试算。
        boolean needMaterialCheck = (operation.getMaterialRequirements() != null && operation.getMaterialRequirements().size() > 0 && operation.getTargetFinishedOperationId() == null) || calbom;


        CopyOnWriteArrayList<GAScheduleResult> machineTasks = getMachineTasks(machineId, chromosome, machineTasksCache);
        GAScheduleResult lastGeneOnMachine = getLastMachineTask(machineTasks);
        int bomtime = 0;
        if (needMaterialCheck&&islockMachineTime) {
            if(!isJit) {
                //正排获取半成品结束时间，如果没有半成品获取原材料时间
                bomtime = getOperationBOMTime(operation, chromosome, earliestStartTime, 2,_globalParam.isIsCheckMp());
                earliestStartTime = Math.max(earliestStartTime, bomtime);
                //倒排需要工序排完再验证原材料，保证bom供应商就行
              //  FileHelper.writeLogFile("工序："+operation.getId()+ "BOMTIME:"+bomtime);
            }
        }


        // 正式落排前，再取一次当前机台最后一道工序，保证换型计算基于最新排程结果。
        if (machineTasks != null && machineTasks.size() > 0 && _globalParam.is_smoothChangeOver()) {
            lastGeneOnMachine = machineTasks.get(machineTasks.size() - 1);
        }
        CopyOnWriteArrayList<ScheduleResultDetail> geneDetails = new CopyOnWriteArrayList<>();
        // 下面开始生成正式的 geneDetails。
        // 与 buildMachinePreview 的区别是：这里得到的结果会继续向下写入 GAScheduleResult，成为真正排程结果。
        BackwardChangeoverHelper backwardChangeoverHelper =
                new BackwardChangeoverHelper(_globalParam, baseTime, machineCalculator);

        // 下面开始生成正式的 geneDetails。
        if (_globalParam.is_smoothChangeOver()) {
            if (isJit && islockMachineTime&&machineTasks!=null&&machineTasks.size()>0) {
                // JIT 倒排 + 换型：同时校验前置换型、当前加工、后置换型能否插入相邻任务窗口。
                BackwardChangeoverHelper.JitBackwardScheduleResult backwardResult =
                        backwardChangeoverHelper.scheduleJitBackwardWithChangeover(machine, operation, earliestStartTime,
                                processingTimeTotal, processingTime, machineTasks, chromosome.getAllOperations());
                if (backwardResult.isForwardFallbackRequired()) {
                    return OperationScheduleResult.forwardFallback();
                }
                geneDetails = backwardResult.getGeneDetails();
                setupTime = backwardResult.getSetupTime();
            } else if (!isJit) {
                // 非 JIT 正排 + 考虑换型：沿用原来的正排换型逻辑。
                Map<Integer, Object> reslte = calculateSetupTime(lastGeneOnMachine, operation, machine, earliestStartTime,
                        processingTimeTotal, _globalParam.is_smoothChangeOverInWeek(), chromosome.getAllOperations());
                setupTime = (int) reslte.get(1);//换型时间
                int setupStartTime = (int) reslte.get(2);//换型开始时间
                earliestStartTime = (int) reslte.get(4);//最早开工时间
                processingTimeTotal = (int) reslte.get(5);//processingTimeTotal
                if (setupTime == 0) {
                    geneDetails = machineCalculator.getNextAvailableTime(machine, operation, earliestStartTime, -1,
                            processingTimeTotal, machineTasks, operation.getIsInterrupt() != 1, true,
                            processingTime, operation.getQuantity(), islockMachineTime, isJit);
                } else {
                    CopyOnWriteArrayList<TimeSegment> AvailableTimeSegment =
                            (CopyOnWriteArrayList<TimeSegment>) reslte.get(6);
                    Map<Integer, Object> result = machineCalculator.CreateScheduleResult(machine, operation,
                            processingTimeTotal, earliestStartTime, AvailableTimeSegment, processingTime,
                            operation.getQuantity(), operation.getIsInterrupt() != 1, setupTime,
                            _globalParam.is_smoothChangeOverInWeek(), setupStartTime, islockMachineTime, isJit);
                    setupTime = (int) result.get(1);
                    operation.setChangeLineTime(setupTime);
                    geneDetails = (CopyOnWriteArrayList<ScheduleResultDetail>) result.get(2);
                }
            } else {
                geneDetails = machineCalculator.getNextAvailableTime(machine, operation, earliestStartTime, -1,
                        processingTimeTotal, machineTasks, operation.getIsInterrupt() != 1, true,
                        processingTime, operation.getQuantity(), islockMachineTime, isJit);
            }
        } else {
            geneDetails = machineCalculator.getNextAvailableTime(machine, operation, earliestStartTime, -1,
                    processingTimeTotal, machineTasks, operation.getIsInterrupt() != 1, true,
                    processingTime, operation.getQuantity(), islockMachineTime, isJit);
        }

//       FileHelper.writeLogFile("  开始    "+operation.getGroupId()+" : "+operation.getId()+",处理时间: " + processingTime + ", 后处理: " + teardownTime +
//                ", 前处理: " + preTime + ", 换型: " + setupTime+ ", 数量: " + operation.getQuantity()+ ", 设备: "+machine.getId()+ ", 是否可中断: "+operation.getIsInterrupt());


        // 确定任务的最早开始时间（基于前一道工序的完整结束时间，包含后处理）


//        System.out.println("      最终最早开始时间: " + earliestStartTime +
//                " (前序工序结束含后处理: " + prevOperationEndTime + ", 设备可用: " +
//                (lastGeneOnMachine != null ? lastGeneOnMachine.getEndTime() : 0) +
//                ", 换型: " + setupTime + ")");


        if (geneDetails == null||geneDetails.size()==0) {

            if(islockMachineTime)
            {
//                FileHelper.writeLogFile("  半成品111111    " + operation.getGroupId() + " - " + operation.getSequence() + ",开始时间: " + 0 + ",结束时间: " + 0 + ",处理时间: " + processingTime + ", 后处理: " + teardownTime +
//                        ", 前处理: " + preTime + ", 换型: " + setupTime + ", 数量: " + operation.getQuantity() + ", 设备: " + machine.getId() + ", 是否可中断: " + operation.getIsInterrupt());

            }
            return  OperationScheduleResult.forwardFallback();



        }

        // startTime 是相对 baseTime 的秒数，0 表示正好从排产基准时间开始，属于合法结果，不能当成失败。
        int startTime = geneDetails.stream()
                .mapToInt(ScheduleResultDetail::getStartTime)
                .min()
                .orElse(0);

            if (startTime < 0) {
                if (isJit && islockMachineTime) {
                    return OperationScheduleResult.forwardFallback();
                }
                return OperationScheduleResult.success(null);

            }
        int endTime = geneDetails.stream()
                .mapToInt(ScheduleResultDetail::getEndTime)
                .max()
                .orElse(0);
        // 不可中断工序不能由多段空档拼接；如果试排结果断开，先归还占用，再倒排寻找最近连续窗口。
        if (operation.getIsInterrupt() != 1 && hasDiscontinuousDetails(geneDetails)) {
            AddMachineAvailable(machine, geneDetails);
            if (isJit && islockMachineTime) {
                CopyOnWriteArrayList<ScheduleResultDetail> continuousDetails =
                        scheduleLatestContinuousJit(machine, operation, earliestStartTime, processingTimeTotal);
                if (continuousDetails == null || continuousDetails.isEmpty()) {
                    return OperationScheduleResult.success(null);
                }
                geneDetails = continuousDetails;
                startTime = geneDetails.stream()
                        .mapToInt(ScheduleResultDetail::getStartTime)
                        .min()
                        .orElse(0);
                endTime = geneDetails.stream()
                        .mapToInt(ScheduleResultDetail::getEndTime)
                        .max()
                        .orElse(0);
            } else {
                return OperationScheduleResult.success(null);
            }
        }
//        if (isJit) {
//            FileHelper.writeLogFile("  半成品    " + operation.getGroupId() + " - " + operation.getSequence() + ",开始时间: " + startTime + ",结束时间: " + endTime + ",处理时间: " + processingTime + ", 后处理: " + teardownTime +
//                    ", 前处理: " + preTime + ", 换型: " + setupTime + ", 数量: " + operation.getQuantity() + ", 设备: " + machine.getId() + ", 是否可中断: " + operation.getIsInterrupt());
//
//        }
        //扣库存
        if (needMaterialCheck && islockMachineTime) {
            if(!isJit) {
                //修改原材料采购时间
                EditOperationBOMTime(operation, chromosome, startTime, machineTasksCache, entryIndexById, scheduleIndexById);
            }else {

                Long maxPurchase = operation.getMaterialRequirements().stream()

                        .filter(t -> "MP".equals(t.getMaterialTypeName())
                                ||( t.getProductOrderID() == null && t.getProductOrderID().isEmpty()))
                        .map(item -> {
                            Long pt = item.getPurchaseTime() == null ? 0L : item.getPurchaseTime();
                            Integer lead = item.getCheckLeadTime() == null ? 0 : item.getCheckLeadTime();
                            return pt + lead;
                        })
                        .max(Long::compareTo).orElse(0L)*24*60*60;

                if(maxPurchase>startTime)
                {
                    int bomtime1 = getOperationBOMTime(operation, chromosome, startTime, 3,_globalParam.isIsCheckMp());
                    if(bomtime1>startTime)
                    {
                        if (isJit && islockMachineTime) {
                            OperationScheduleResult result=  OperationScheduleResult.forwardFallback();
                            result.setStartTime(bomtime1);
                            return result;
                        }
                    }else
                    {


                       // EditOperationBOMTime(operation, chromosome, startTime, machineTasksCache, entryIndexById, scheduleIndexById);

                    }
                }

            }
        }
        //换型时间是否占用设备加工时间
        //10:00 开始上班  前面的任务：24:00 结束 开始换型 休息时间 10小时
        // 换型时间 12小时
        // 换型时间 - 中间休息时间 =2小时
        //开工时间需往后延 2小时


        // 准备工时 加入到加工时间里

        // 后处理时间 相同任务的前一工序的结束时间+后处理时间 =当前工序最早开工时间


        GAScheduleResult result = CreateResult(operation, machine.getId(), startTime, endTime, processingTime, setupTime, preTime, teardownTime, bomtime, geneDetails, existingResult,machine.getCapacityTypeName(),isJit);


//        System.out.println("huanxingshijian="+result.getChangeOverTime()+"-------------------"+result.getOrderId()+"--------"+result.getExecId()+"---------"+prev.getOrderId()+"--------"+prev.getExecId());
        if (islockMachineTime)
        {
            chromosome.getResult().add(result);
        machine.setLastGene(result);

//        FileHelper.writeLogFile("  结束    "+ConvertTime(startTime)+"--"+ConvertTime(endTime)+"   "+operation.getGroupId()+" : "+operation.getId()+",处理时间: " + processingTime + ", 后处理: " + teardownTime +
//                ", 前处理: " + preTime + ", 换型: " + setupTime+ ", 数量: " + operation.getQuantity()+ ", 设备: "+machine.getId()+ ", 是否可中断: "+operation.getIsInterrupt());
        if (machineTasks != null) {
            machineTasks.add(result);
        }
        scheduleIndexById.put(operation.getId(), result);
    }
//        long pwsElapsed = System.nanoTime() - pwsStart;
//        if (pwsElapsed > 500_000_000L) {
//            FileHelper.writeLogFile("[PERF] processWithSingleMachine 总慢 opId=" + operationId
//                    + ", groupId=" + operation.getGroupId() + ", machineId=" + machineId
//                    + ", hasBOM=" + commitMaterialCheck + ", 耗时=" + fmtMs(pwsElapsed));
//        }
        return OperationScheduleResult.success(result);
    }

    // 判断排程明细是否存在断档。不可中断工序如果出现断档，页面外层时间会跨住中间任务。
    private boolean hasDiscontinuousDetails(CopyOnWriteArrayList<ScheduleResultDetail> geneDetails) {
        if (geneDetails == null || geneDetails.size() <= 1) {
            return false;
        }

        List<int[]> ranges = new ArrayList<>();
        for (ScheduleResultDetail detail : geneDetails) {
            if (detail == null) {
                continue;
            }
            if (detail.getUsedSegment() != null && !detail.getUsedSegment().isEmpty()) {
                for (TimeSegment segment : detail.getUsedSegment()) {
                    if (segment == null || segment.getStart() == null || segment.getEnd() == null) {
                        continue;
                    }
                    int segmentStart = (int) ChronoUnit.SECONDS.between(baseTime, segment.getStart());
                    int segmentEnd = (int) ChronoUnit.SECONDS.between(baseTime, segment.getEnd());
                    if (segmentEnd > segmentStart) {
                        ranges.add(new int[]{segmentStart, segmentEnd});
                    }
                }
            } else if (detail.getEndTime() > detail.getStartTime()) {
                ranges.add(new int[]{detail.getStartTime(), detail.getEndTime()});
            }
        }

        if (ranges.size() <= 1) {
            return false;
        }

        ranges.sort(Comparator.comparingInt(range -> range[0]));
        int lastEnd = ranges.get(0)[1];
        for (int i = 1; i < ranges.size(); i++) {
            int[] current = ranges.get(i);
            if (current[0] > lastEnd + 1) {
                return true;
            }
            lastEnd = Math.max(lastEnd, current[1]);
        }
        return false;
    }

    // 倒排不可中断兜底：从锚点往前找最近的一整段连续空闲窗口，避免失败后掉到基准日期正排。
    private CopyOnWriteArrayList<ScheduleResultDetail> scheduleLatestContinuousJit(
            Machine machine, Entry operation, int latestEndTime, int processingTimeTotal) {
        if (machine == null || machine.getAvailability() == null || processingTimeTotal <= 0) {
            return null;
        }

        LocalDateTime latestEnd = baseTime.plusSeconds(latestEndTime);
        List<TimeSegment> availableSegments = machine.getAvailability().stream()
                .filter(t -> t != null
                        && !t.isUsed()
                        && t.getStart() != null
                        && t.getEnd() != null
                        && t.getType() != SegmentType.MAINTENANCE
                        && t.getStart().isBefore(latestEnd)
                        && t.getEnd().isAfter(baseTime))
                .sorted(Comparator.comparing(TimeSegment::getStart))
                .collect(Collectors.toList());

        List<TimeSegment> group = new ArrayList<>();
        LocalDateTime groupStart = null;
        LocalDateTime groupEnd = null;
        long groupAvailableSeconds = 0L;

        for (int i = availableSegments.size() - 1; i >= 0; i--) {
            TimeSegment segment = availableSegments.get(i);
            LocalDateTime segmentStart = segment.getStart().isBefore(baseTime) ? baseTime : segment.getStart();
            LocalDateTime segmentEnd = segment.getEnd().isAfter(latestEnd) ? latestEnd : segment.getEnd();
            if (!segmentEnd.isAfter(segmentStart)) {
                continue;
            }

            boolean continuous = group.isEmpty() || !segmentEnd.plusSeconds(1).isBefore(groupStart);
            if (!continuous) {
                group.clear();
                groupAvailableSeconds = 0L;
                groupEnd = null;
            }

            group.add(0, segment);
            groupStart = segmentStart;
            if (groupEnd == null) {
                groupEnd = segmentEnd;
            }
            groupAvailableSeconds += ChronoUnit.SECONDS.between(segmentStart, segmentEnd);

            if (groupAvailableSeconds >= processingTimeTotal) {
                return buildContinuousJitDetails(machine, operation, group, groupEnd, processingTimeTotal);
            }
        }

        return null;
    }

    // 将选中的连续窗口转成明细，并同步占用设备日历。
    private CopyOnWriteArrayList<ScheduleResultDetail> buildContinuousJitDetails(
            Machine machine, Entry operation, List<TimeSegment> group, LocalDateTime latestEnd, int processingTimeTotal) {
        CopyOnWriteArrayList<ScheduleResultDetail> details = new CopyOnWriteArrayList<>();
        long remaining = processingTimeTotal;
        LocalDateTime cursorEnd = latestEnd;

        for (int i = group.size() - 1; i >= 0 && remaining > 0; i--) {
            TimeSegment segment = group.get(i);
            LocalDateTime useEnd = segment.getEnd().isAfter(cursorEnd) ? cursorEnd : segment.getEnd();
            LocalDateTime useStart = segment.getStart();
            if (!useEnd.isAfter(useStart)) {
                continue;
            }

            long availableSeconds = ChronoUnit.SECONDS.between(useStart, useEnd);
            if (availableSeconds > remaining) {
                useStart = useEnd.minusSeconds(remaining);
            }

            TimeSegment occupied = occupyAvailabilityRange(machine, segment, useStart, useEnd);
            if (occupied == null) {
                return null;
            }

            ScheduleResultDetail detail = new ScheduleResultDetail();
            detail.setKey(occupied.getKey());
            detail.setStartTime((int) ChronoUnit.SECONDS.between(baseTime, useStart));
            detail.setEndTime((int) ChronoUnit.SECONDS.between(baseTime, useEnd));
            detail.setOneTime(1);
            detail.setQuantity(operation.getQuantity());
            detail.setEfficiency(occupied.getEfficiency());
            detail.setUsedSegment(Collections.singletonList(occupied));
            details.add(0, detail);

            remaining -= ChronoUnit.SECONDS.between(useStart, useEnd);
            cursorEnd = useStart.minusSeconds(1);
        }

        return remaining <= 0 ? details : null;
    }

    // 从设备可用片段里切出本次占用范围，保留前后未占用部分。
    private TimeSegment occupyAvailabilityRange(
            Machine machine, TimeSegment source, LocalDateTime useStart, LocalDateTime useEnd) {
        if (machine == null || machine.getAvailability() == null || source == null
                || useStart == null || useEnd == null || !useEnd.isAfter(useStart)) {
            return null;
        }

        int index = machine.getAvailability().stream()
                .filter(t -> source.getKey().equals(t.getKey()))
                .findFirst()
                .map(machine.getAvailability()::indexOf)
                .orElse(-1);
        if (index < 0) {
            return null;
        }

        TimeSegment current = machine.getAvailability().remove(index);
        List<TimeSegment> replacement = new ArrayList<>();
        if (current.getStart().isBefore(useStart)) {
            TimeSegment before = copyAvailabilitySegment(current, current.getStart(), useStart.minusSeconds(1), false);
            if (before.getEnd().isAfter(before.getStart())) {
                replacement.add(before);
            }
        }

        TimeSegment occupied = copyAvailabilitySegment(current, useStart, useEnd, true);
        replacement.add(occupied);

        if (current.getEnd().isAfter(useEnd)) {
            TimeSegment after = copyAvailabilitySegment(current, useEnd.plusSeconds(1), current.getEnd(), false);
            if (after.getEnd().isAfter(after.getStart())) {
                replacement.add(after);
            }
        }

        machine.getAvailability().addAll(replacement);
        machine.getAvailability().sort(Comparator.comparing(TimeSegment::getStart));
        return occupied;
    }

    private TimeSegment copyAvailabilitySegment(
            TimeSegment source, LocalDateTime start, LocalDateTime end, boolean used) {
        TimeSegment copy = new TimeSegment();
        copy.setKey(UUID.randomUUID().toString());
        copy.setStart(start);
        copy.setEnd(end);
        copy.setEarliestTime(source.getEarliestTime());
        copy.setTotalTaskTime(source.getTotalTaskTime());
        copy.setType(source.getType());
        copy.setHoliday(source.isHoliday());
        copy.setUsed(used);
        copy.setEfficiency(source.getEfficiency());
        copy.setProcessingTime(source.getProcessingTime());
        return copy;
    }

    private GAScheduleResult CreateResult(Entry operation,long machineId
            ,int startTime,int endTime,double processingTime
            ,int setupTime,int preTime,int teardownTime,int bomtime
            ,CopyOnWriteArrayList<ScheduleResultDetail> geneDetails,GAScheduleResult existingResult,String capacityTypeName,boolean isJit )
    {
        GAScheduleResult result=new GAScheduleResult();

        result.setGroupId(operation.getGroupId());
        result.setOperationId(operation.getId());
        result.setIsJit(isJit);
        result.setExecId(operation.getExecId());
        result.setOrderId(operation.getOrderId());
        result.setOrderCode(operation.getOrderCode());
        result.setProductId(operation.getProductId());
        result.setProductName(operation.getProductName());
        result.setProductCode(operation.getProductCode());
        result.setTargetFinishedOperationId(operation.getTargetFinishedOperationId() == null
                ? null
                : new ArrayList<>(operation.getTargetFinishedOperationId()));
        result.setMachineId(machineId);
        result.setCapacityTypeName(capacityTypeName);
        result.setStartTime(startTime);
        result.setEndTime(endTime);
        result.setOneTime(processingTime);
        result.setQuantity(operation.getQuantity());
        result.setChangeOverTime(setupTime);
        result.setPreTime(preTime);
        result.setTeardownTime(teardownTime);
        result.setBomTime(bomtime);
        if(existingResult!=null) {
            if(existingResult.getLockStartTime()==1) {
                result.setLockStartTime(existingResult.getLockStartTime());
                result.setDesignatedStartTime(existingResult.getDesignatedStartTime());
            }
        }

        int processingTimeTotal1=0;
if(geneDetails!=null&&geneDetails.size()>0)
{
    processingTimeTotal1=(int) geneDetails.stream().filter(t->t.getUsedSegment()==null).mapToDouble(ScheduleResultDetail::getProcessingTime) // 替换为实际字段名
            .sum();

    List<TimeSegment> UsedSegments=geneDetails.stream().
            filter(t->t.getUsedSegment()!=null)
            .map(ScheduleResultDetail::getUsedSegment).flatMap(List::stream)
            // 收集为最终的 List
            .collect(Collectors.toList());

    if(UsedSegments!=null&&UsedSegments.size()>0)
    {
        processingTimeTotal1+=(int)UsedSegments.stream().mapToDouble(TimeSegment::getProcessingTime) // 替换为实际字段名
                .sum();
    }



    result.setGeneDetails(geneDetails);
}else {
    processingTimeTotal1=endTime-startTime;
}
        result.setProcessingTime(processingTimeTotal1);

        return  result;
    }

       private void updateSemiJitTargets(Entry parentOperation, int parentStartTime, Chromosome chromosome) {
        if (parentOperation.getDependentOnOrderIds() == null || parentOperation.getDependentOnOrderIds().isEmpty()) {
            return;
        }
        LocalDateTime targetTime = baseTime.plusSeconds(parentStartTime)
                .minusMinutes(Math.max(0, _globalParam.getSemiJitBufferMinutes()));
        if (targetTime.isBefore(baseTime)) {
            targetTime = baseTime;
        }
        for (Integer childGroupId : parentOperation.getDependentOnOrderIds()) {
            List<Entry> childOperations = chromosome.getAllOperations().stream()
                    .filter(t -> t.getGroupId() == childGroupId)
                    .collect(Collectors.toList());
            if (childOperations.isEmpty()) {
                continue;
            }
            int maxSequence = childOperations.stream().mapToInt(Entry::getSequence).max().orElse(Integer.MIN_VALUE);
            for (Entry childOperation : childOperations) {
                if (childOperation.getSequence() != maxSequence) {
                    continue;
                }
                if (childOperation.getLatestCompletionTime() == null || targetTime.isBefore(childOperation.getLatestCompletionTime())) {
                    childOperation.setLatestCompletionTime(targetTime);
                }
                if (childOperation.getTargetFinishedOperationId() == null) {
                    childOperation.setTargetFinishedOperationId(new ArrayList<>());
                }
                if (!childOperation.getTargetFinishedOperationId().contains(parentOperation.getId())) {
                    childOperation.getTargetFinishedOperationId().add(parentOperation.getId());
                }
            }
        }
    }

    /**
     * 按当前候选开工时间做一次机台侧试排。
     * 注意：该方法会临时占用 machine.availability 中对应的时段，调用方用完后必须配合 AddMachineAvailable 释放。
     */
    private MachineSchedulePreview buildMachinePreview(Entry operation, Machine machine, double processingTime, int processingTimeTotal,
                                                       int earliestStartTime, GAScheduleResult lastGeneOnMachine,
                                                       CopyOnWriteArrayList<GAScheduleResult> machineTasks, Chromosome chromosome) {
        int setupTime = 0;
        int previewStart = earliestStartTime;
        int previewProcessingTotal = processingTimeTotal;
        CopyOnWriteArrayList<ScheduleResultDetail> geneDetails;

        if (_globalParam.is_smoothChangeOver()) {
            // 先把换型时间、换型起点以及加工总时长修正到当前候选时间点。
            Map<Integer,Object> reslte = calculateSetupTime(lastGeneOnMachine, operation, machine, previewStart, previewProcessingTotal, _globalParam.is_smoothChangeOverInWeek(),chromosome.getAllOperations());
            setupTime=(int)reslte.get(1);
            int setupStartTime=(int)reslte.get(2);
            previewStart=(int)reslte.get(4);
            previewProcessingTotal=(int)reslte.get(5);
            if(setupTime==0)
            {
                // 没有换型占用时，直接查机台下一段可排的可用窗口。
                geneDetails = machineCalculator.getNextAvailableTime(machine, operation, previewStart, -1,
                        previewProcessingTotal, machineTasks, operation.getIsInterrupt()!=1, true,processingTime, operation.getQuantity(), true,false);

            }else {
                // 有换型占用时，需要把换型段和加工段一起拼成完整的试排结果。
                CopyOnWriteArrayList<TimeSegment> AvailableTimeSegment = (CopyOnWriteArrayList<TimeSegment>) reslte.get(6);
                Map<Integer,Object> result = machineCalculator.CreateScheduleResult(machine, operation, previewProcessingTotal, previewStart,
                        AvailableTimeSegment, processingTime, operation.getQuantity(), operation.getIsInterrupt() != 1, setupTime, _globalParam.is_smoothChangeOverInWeek(), setupStartTime,true,false);

                setupTime=(int)result.get(1);
                geneDetails=(CopyOnWriteArrayList<ScheduleResultDetail>) result.get(2);
            }
        }else {
            // 不考虑平滑换型时，只需要找加工段可用窗口。
            geneDetails = machineCalculator.getNextAvailableTime(machine, operation, previewStart, -1,
                    previewProcessingTotal, machineTasks, operation.getIsInterrupt()!=1, true,processingTime, operation.getQuantity(), true,false);
        }

        // geneDetails 可能跨多个班次/时段，开始时间取最小值，结束时间取最大值。
        int startTime = geneDetails.stream()
                .mapToInt(ScheduleResultDetail::getStartTime)
                .min()
                .orElse(0);
        int endTime = geneDetails.stream()
                .mapToInt(ScheduleResultDetail::getEndTime)
                .max()
                .orElse(0);
        return new MachineSchedulePreview(startTime, endTime, setupTime, geneDetails);
    }

    // 按机台缓存已排结果，避免固定点迭代期间反复全表扫描 chromosome.getResult()。
    public CopyOnWriteArrayList<GAScheduleResult> getMachineTasks(long machineId, Chromosome chromosome,
                                                                   Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache) {
        if (machineTasksCache.containsKey(machineId)) {
            return machineTasksCache.get(machineId);
        }
        CopyOnWriteArrayList<GAScheduleResult> machineTasks = chromosome.getResult().stream()
                .filter(t -> t.getMachineId() == machineId)
                .sorted(Comparator.comparingInt(GAScheduleResult::getStartTime))
                .collect(Collectors.toCollection(CopyOnWriteArrayList::new));
        machineTasksCache.put(machineId, machineTasks);
        return machineTasks;
    }

    // 当前机台最后一道已排工序，用于约束连续排程和换型起点。
    private GAScheduleResult getLastMachineTask(CopyOnWriteArrayList<GAScheduleResult> machineTasks) {
        if(machineTasks!=null&&machineTasks.size()>0)
        {
            return machineTasks.get(machineTasks.size()-1);
        }
        return null;
    }

    // trial BOM 恢复快照后，旧的 Machine 引用可能已经失效，因此统一从 chromosome 中重新取当前有效对象。
    private Machine getMachineById(Chromosome chromosome, long machineId) {
        return chromosome.getMachines().stream()
                .filter(m -> m.getId() == machineId)
                .findFirst()
                .orElse(null);
    }

    /**
     * 单道序排程结果。
     * scheduleResult 用于正常推进订单进度；forwardFallbackRequired 用于把“整单转正排”显式带回外层。
     */
    private static class OperationScheduleResult {
        private final GAScheduleResult scheduleResult;
        private  int startTime;
        private final boolean forwardFallbackRequired;

        private OperationScheduleResult(GAScheduleResult scheduleResult, boolean forwardFallbackRequired,int startTime) {
            this.scheduleResult = scheduleResult;
            this.forwardFallbackRequired = forwardFallbackRequired;
            this.startTime=startTime;
        }

        private static OperationScheduleResult success(GAScheduleResult scheduleResult) {
            return new OperationScheduleResult(scheduleResult, false,0);
        }

        private static OperationScheduleResult forwardFallback() {
            return new OperationScheduleResult(null, true,0);
        }
        public int getStartTime() {
            return startTime;
        }

        public void  setStartTime(int startTime){this.startTime=startTime;}
        private GAScheduleResult getScheduleResult() {
            return scheduleResult;
        }

        private int getEndTime() {
            return scheduleResult == null ? 0 : scheduleResult.getEndTime();
        }

        private boolean isForwardFallbackRequired() {
            return forwardFallbackRequired;
        }
    }

    private static class MachineSchedulePreview {
        private final int startTime;
        private final int endTime;
        private final int setupTime;
        private final CopyOnWriteArrayList<ScheduleResultDetail> geneDetails;

        private MachineSchedulePreview(int startTime, int endTime, int setupTime, CopyOnWriteArrayList<ScheduleResultDetail> geneDetails) {
            this.startTime = startTime;
            this.endTime = endTime;
            this.setupTime = setupTime;
            this.geneDetails = geneDetails;
        }

        public int getStartTime() {
            return startTime;
        }

        public int getEndTime() {
            return endTime;
        }

        public int getSetupTime() {
            return setupTime;
        }

        public CopyOnWriteArrayList<ScheduleResultDetail> getGeneDetails() {
            return geneDetails;
        }
    }

    /**
     * 计算前序结束时间
     * @param prevtime
     * @param currentOp
     * @param chromosome
     * @return
     */
    private  int CalPrevtime(int prevtime,Entry currentOp,Chromosome chromosome,double processTime,Machine machine,Map<Integer, Entry> entryIndexById,Map<Integer, GAScheduleResult> scheduleIndexById) {
        List<OperationDependency> FsOperations = currentOp.getPrevEntryIds().stream()
                .filter(t -> t.getDependencyType() == DependencyType.FinishToStart)
                .collect(Collectors.toList());//串行
        if (FsOperations != null && FsOperations.size() > 0) {
            for (OperationDependency opid : FsOperations) {
//                List<GAScheduleResult> prevOperations = chromosome.getResult().stream()
//                        .filter(t ->  t.getOperationId() == opid.getPrevOperationId())
//                        .collect(Collectors.toList());//
                GAScheduleResult prevOp= scheduleIndexById.get(opid.getPrevOperationId());
                // for (GAScheduleResult prevOp : prevOperations) {
                if(prevOp!=null){
                    //加上后处理时间
                    prevtime = Math.max(prevtime, prevOp.getEndTime() + currentOp.getTeardownTime());
                }
            }
        }
        //重叠
        List<OperationDependency> SSOperations = currentOp.getPrevEntryIds().stream()
                .filter(t -> t.getDependencyType() == DependencyType.Overlapping)
                .collect(Collectors.toList());//重叠
        if (SSOperations != null && SSOperations.size() > 0) {
            List<GAScheduleResult> newScheduleResult = new ArrayList<>();
            List<ScheduleResultDetail> newScheduleResultDetails = new ArrayList<>();

            for (int j=0;j<SSOperations.size();j++)
            {
                OperationDependency opid=SSOperations.get(j);
//                List<GAScheduleResult> prevOperations = chromosome.getResult().stream()
//                        .filter(t ->  t.getOperationId() == opid.getPrevOperationId())
//                        .collect(Collectors.toList());//多台
                GAScheduleResult prevOp= scheduleIndexById.get(opid.getPrevOperationId());

                // for (GAScheduleResult prevOp : prevOperations) {
                if(prevOp!=null){
                    newScheduleResult.add(prevOp);
                    newScheduleResultDetails.addAll(prevOp.getGeneDetails());
                }
                if(j==SSOperations.size()-1)
                {
                    int prevtime1 = CalSSPrevtime(newScheduleResult,newScheduleResultDetails, prevtime, currentOp, chromosome, processTime, machine);
                    prevtime = Math.max(prevtime, prevtime1);

                }else {
//                    Entry entry=  chromosome.getAllOperations().stream()
//                            .filter(t->t.getId()==opid.getPrevOperationId())
//                            .findFirst().orElse(null);
                    Entry entry=entryIndexById.get(opid.getPrevOperationId());
                    OperationDependency opid2=SSOperations.get(j+1);
//                    Entry entry1=  chromosome.getAllOperations().stream()
//                            .filter(t->t.getId()==opid2.getPrevOperationId())
//                            .findFirst().orElse(null);
                    Entry entry1=entryIndexById.get(opid2.getPrevOperationId());
//不是同一前工序，效率不能合并   newScheduleResult 清空,如何是一个工序就合并计算
                    if(entry!=null&&entry1!=null&&entry.getRoutingDetailId()!=entry1.getRoutingDetailId())
                    {

                        int prevtime1 = CalSSPrevtime(newScheduleResult,newScheduleResultDetails, prevtime, currentOp, chromosome, processTime, machine);
                        prevtime = Math.max(prevtime, prevtime1);

                        newScheduleResult.clear();
                        newScheduleResultDetails.clear();
                    }
                }
            }




        }
        return prevtime;

    }

    /**
     * 计算后序结束时间
     * @param nexttime
     * @param currentOp
     * @param chromosome
     * @return
     */
    private  int CalNexttime(int nexttime,Entry currentOp,Chromosome chromosome,double processTime,Machine machine,Map<Integer, Entry> entryIndexById,Map<Integer, GAScheduleResult> scheduleIndexById) {
        List<OperationDependency> FsOperations = currentOp.getNextEntryIds().stream()
                .filter(t -> t.getDependencyType() == DependencyType.FinishToStart)
                .collect(Collectors.toList());//串行
        if (FsOperations != null && FsOperations.size() > 0) {
            for (OperationDependency opid : FsOperations) {
//                List<GAScheduleResult> prevOperations = chromosome.getResult().stream()
//                        .filter(t ->  t.getOperationId() == opid.getPrevOperationId())
//                        .collect(Collectors.toList());//
                GAScheduleResult nextOp= scheduleIndexById.get(opid.getNextOperationId());
                // for (GAScheduleResult prevOp : prevOperations) {
                if(nextOp!=null){
                    //加上后处理时间
                    nexttime =Math.min(nexttime,nextOp.getStartTime());
                }
            }
        }

        return nexttime-currentOp.getTeardownTime();

    }


    private  int CalSSPrevtime(List<GAScheduleResult> newScheduleResult,List<ScheduleResultDetail> newScheduleResultDetails,int prevtime,Entry currentOp,Chromosome chromosome,double processTime,Machine machine)
    {
        int prevperationEndTime = newScheduleResult.stream()
                .mapToInt(GAScheduleResult::getEndTime)
                .max()
                .orElse(0);
        //   prevtime = calculateNextOperationStartTime(newScheduleResult, newScheduleResultDetails, 0, processTime);
        // 下一工序结束时间需晚于上一工序结束时间一个产品加工时间

        int ssStartTimeWithCalendar = calculateSSStartTimeWithCalendar(
                newScheduleResult,
                newScheduleResultDetails,
                currentOp,
                machine,
                processTime,
                prevtime);
//
        prevtime = Math.max(prevtime, ssStartTimeWithCalendar);


        double nextopplanend = prevperationEndTime + processTime;

        List<ScheduleResultDetail> geneDetails1 = machineCalculator.checkMachineStartTime(machine, (int) (processTime * currentOp.getQuantity()),
                baseTime.plusSeconds((int) nextopplanend),
                baseTime.plusSeconds(prevtime),
                chromosome.getResult());

        if (geneDetails1 != null && !geneDetails1.isEmpty()) {
            prevtime = Math.max(prevtime,
                    geneDetails1.stream()
                            .mapToInt(ScheduleResultDetail::getStartTime)
                            .min()
                            .orElse(prevtime)
            );

        }
        return prevtime;
    }


    /**
     * 汇总当前工序的物料约束，返回所有原料/半成品中最晚满足的那个时刻。
     * 返回值含义是“这道工序最早允许因物料而开工的秒数”。
     */
    private int getOperationBOMTime(Entry currentOp, Chromosome chromosome,int estimatedStartTime,int bomtype,boolean isCheckMp ) {

        List<OrderMaterialRequirement> opboms=  currentOp.getMaterialRequirements();
        //if(opboms==null||!_globalParam.isIsCheckMp())
        if(opboms==null)
        {
            return  0;
        }


        int rawTime = 0, sfTime = 0;
        if (opboms != null && !opboms.isEmpty()) {
            // 计算RawTime
            if (bomtype == 0 || bomtype == 1) {
                Optional<LocalDateTime> rawDateOpt = opboms.stream()
                        .filter(t -> "MP".equals(t.getMaterialTypeName())||( t.getProductOrderID() == null || t.getProductOrderID().isEmpty()))
                        .map(OrderMaterialRequirement::getUseTime)
                        .filter(Objects::nonNull)
                        .max(LocalDateTime::compareTo);
                if (rawDateOpt.isPresent()) {
                    rawTime = (int) Duration.between(baseTime, rawDateOpt.get()).getSeconds();
                }
            }


            if (bomtype == 0 || bomtype == 2) {
                // 计算SFTime
                List<OrderMaterialRequirement> sfBoms = opboms.stream()
                        .filter(t -> !"MP".equals(t.getMaterialTypeName())
                                && t.getProductOrderID() != null && !t.getProductOrderID().isEmpty())
                        .collect(Collectors.toList());

                if (!sfBoms.isEmpty() && sfBoms.size() > 0) {
                    for (OrderMaterialRequirement sf : sfBoms) {

                        for (int orderid : sf.getProductOrderID()) {
                            int sfTime1 = 0;
                            List<GAScheduleResult> result = chromosome.getResult();
                            List<GAScheduleResult> oe = result.stream()
                                    .filter(t -> t.getGroupId() == orderid)
                                    .collect(Collectors.toList());
                            if (!oe.isEmpty()) {
                                int CkeckLeadTime = 0;
                                if (sf.getCheckLeadTime() != null) {
                                    CkeckLeadTime = (int) (sf.getCheckLeadTime() * 24 * 60);
                                }
                                sfTime1 = oe.stream().mapToInt(GAScheduleResult::getEndTime).max().orElse(0)
                                        + CkeckLeadTime;

                                sf.setUseTime(baseTime.plusSeconds(sfTime1));
                            }
                            sfTime = Math.max(sfTime, sfTime1);
                        }
                    }
                }else {
                    if ( bomtype == 2) {

                        Map<String, OrderMaterialRequirement> totalNeededByMaterial = new HashMap<>();

                        for (OrderMaterialRequirement req : opboms) {
                            OrderMaterialRequirement reqq = totalNeededByMaterial.get(req.getMaterialId());
                            if (reqq != null) {
                                double allneeded = req.getSpentQty() / req.getMainQty() * currentOp.getQuantity();
                                allneeded = reqq.getRequiredQuantity() + allneeded;
                                reqq.setRequiredQuantity(allneeded);
                                reqq.setQjQty(allneeded);
                            } else {
                                OrderMaterialRequirement reqq1 = ProductionDeepCopyUtil.deepCopy(req);

                                double allneeded = req.getSpentQty() / req.getMainQty() * currentOp.getQuantity();

                                reqq1.setRequiredQuantity(allneeded);
                                reqq1.setQjQty(allneeded);
                                totalNeededByMaterial.put(req.getMaterialId(), reqq1);
                            }
                        }

                        List<OrderMaterialRequirement> remove=new ArrayList<>();
                         materialRequirementService.CalBom(chromosome,0, totalNeededByMaterial,chromosome.getMaterials(),baseTime.plusSeconds(estimatedStartTime) ,false,remove,null,false, isCheckMp);
                        Optional<LocalDateTime> rawDateOpt =  totalNeededByMaterial.values().stream()

                                .map(OrderMaterialRequirement::getUseTime)
                                .filter(Objects::nonNull)
                                .max(LocalDateTime::compareTo);
                        if (rawDateOpt.isPresent()) {
                            rawTime = (int) Duration.between(baseTime, rawDateOpt.get()).getSeconds();
                        }
                    }
                }
            }

            if (bomtype == 0 || bomtype == 1) {
                Optional<LocalDateTime> sfDateOpt = opboms.stream()
                        .filter(t -> !"MP".equals(t.getMaterialTypeName()) && (t.getProductOrderID() == null || t.getProductOrderID().isEmpty()))
                        .map(OrderMaterialRequirement::getUseTime)
                        .filter(Objects::nonNull)
                        .max(LocalDateTime::compareTo);
                if (sfDateOpt.isPresent()) {
                    sfTime = Math.max(sfTime, (int) Duration.between(baseTime, sfDateOpt.get()).getSeconds());
                }

            }

            if ( bomtype == 3) {

                Map<String, OrderMaterialRequirement> totalNeededByMaterial = new HashMap<>();
                List<OrderMaterialRequirement> mpBoms = opboms.stream()
                        .filter(t -> "MP".equals(t.getMaterialTypeName())
                                ||( t.getProductOrderID() == null && t.getProductOrderID().isEmpty()))
                        .collect(Collectors.toList());



                for (OrderMaterialRequirement req : mpBoms) {
                    OrderMaterialRequirement reqq = totalNeededByMaterial.get(req.getMaterialId());
                    if (reqq != null) {
                        double allneeded = req.getSpentQty() / req.getMainQty() * currentOp.getQuantity();
                        allneeded = reqq.getRequiredQuantity() + allneeded;
                        reqq.setRequiredQuantity(allneeded);
                        reqq.setQjQty(allneeded);
                    } else {
                        OrderMaterialRequirement reqq1 = ProductionDeepCopyUtil.deepCopy(req);

                        double allneeded = req.getSpentQty() / req.getMainQty() * currentOp.getQuantity();

                        reqq1.setRequiredQuantity(allneeded);
                        reqq1.setQjQty(allneeded);
                        totalNeededByMaterial.put(req.getMaterialId(), reqq1);
                    }
                }
                List<OrderMaterialRequirement> remove=new ArrayList<>();
                materialRequirementService.CalBom(chromosome,0, totalNeededByMaterial,chromosome.getMaterials(),baseTime.plusSeconds(estimatedStartTime) ,false,remove,null,false, isCheckMp);
                Optional<LocalDateTime> rawDateOpt =  totalNeededByMaterial.values().stream()

                        .map(OrderMaterialRequirement::getUseTime)
                        .filter(Objects::nonNull)
                        .max(LocalDateTime::compareTo);
                if (rawDateOpt.isPresent()) {
                    rawTime = (int) Duration.between(baseTime, rawDateOpt.get()).getSeconds();
                }
            }

        }
        return Math.max(rawTime, sfTime);
    }

    // 默认走正式提交路径，调用方不传 commitChanges 时认为要把物料状态真实写回。
    private int EditOperationBOMTime(Entry currentOp, Chromosome chromosome,int earliestStartTime,Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,Map<Integer, Entry> entryIndexById,Map<Integer, GAScheduleResult> scheduleIndexById) {

        LocalDateTime earliestStartTime1 = baseTime.plusSeconds(earliestStartTime);

        materialRequirementService.EditOperationBOM(currentOp, chromosome, earliestStartTime1, this, machineTasksCache, entryIndexById, scheduleIndexById, baseTime, true);

        return 0;
    }


    public void EditorderOperation(Chromosome chromosome, int groupId,double needed,Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,Map<Integer, Entry> entryIndexById,Map<Integer, GAScheduleResult> scheduleIndexById){
        List<Entry> orderOps = chromosome.getAllOperations().stream()
                .filter(t -> t.getGroupId() == groupId)
                .sorted(Comparator.comparing(Entry::getSequence))
                .collect(Collectors.toList());

        List<GlobalOperationInfo> entrys=
                chromosome.getGlobalOpList().stream().filter(t->t.getOp().getGroupId()==groupId).collect(Collectors.toList());


        for (Entry currentOp : orderOps) {

            if(currentOp.isNewCreate()) {
                currentOp.setQuantity(needed);
            }



            GlobalOperationInfo global=  entrys.stream().
                    filter(t->t.getOp().getId()==currentOp.getId())
                    .findFirst().orElse(null);

            int globalOpId= global.getGlobalOpId();

           int machineSeq= chromosome.getMachineSelection().get(globalOpId);
            MachineOption   machineOption=
                    currentOp.getMachineOptions().get(machineSeq-1);
            Long machineId = machineOption.getMachineId();


//            MachineOption   machineOption= currentOp.getMachineOptions().stream()
//                    .filter(t->t.getMachineId().equals(machineId)).findFirst().orElse(null);
            double processTime = machineOption.getProcessingTime();
            OpMachine opMachine=new OpMachine();
            opMachine.setGroupId(groupId);
            opMachine.setSequence(currentOp.getSequence());
            opMachine.setMachineId(machineId);
            opMachine.setProcessingTime(machineOption.getProcessingTime());
            opMachine.setRuntime(machineOption.getRuntime());
            opMachine.setSingleOut(machineOption.getSingleOut());

            Machine targetMachine = chromosome.getMachines().stream()
                    .filter(m -> m.getId() == machineId)
                    .findFirst()
                    .orElse(null);

            int prevtime = 0;
            //后处理时间
            int teardownTime = currentOp.getTeardownTime();
            if (!currentOp.getPrevEntryIds().isEmpty()) {
                // 处理多个前工序
                prevtime= CalPrevtime( prevtime, currentOp, chromosome, processTime, targetMachine, entryIndexById,scheduleIndexById);
            }

            // 上个离散参数
            //  String lastDiscreteParameter = machineState.get(machineId);

            int prevendtime=prevtime;

            Machine machine = chromosome.getMachines().stream()
                    .filter(m -> m.getId() == machineId)
                    .findFirst()
                    .orElse(null);
// 缓存机器任务
            OperationScheduleResult operationResult = processWithSingleMachine(currentOp, machine, processTime,
                    prevtime, opMachine, chromosome, true, prevendtime, machineTasksCache, entryIndexById,
                    scheduleIndexById, true, true);
            if (operationResult.isForwardFallbackRequired()) {
                return;
            }


        }

    }

    public void ClearorderOperationResult(Chromosome chromosome, int groupId){

        List<Entry> orderOps = chromosome.getAllOperations().stream()
                .filter(t -> t.getGroupId() == groupId)
                .sorted(Comparator.comparing(Entry::getSequence))
                .collect(Collectors.toList());
        for (Entry currentOp : orderOps) {
            GAScheduleResult existingResult = chromosome.getResult().stream()
                    .filter(r-> r.getOperationId() == currentOp.getId())
                    .findFirst().orElse(null);

            if(existingResult==null)
            {
                continue;
            }
            Long machineId = existingResult.getMachineId();

            Machine machine = chromosome.getMachines().stream()
                    .filter(m -> m.getId() == machineId)
                    .findFirst()
                    .orElse(null);

            AddMachineAvailable(machine,existingResult.getGeneDetails());
            chromosome.getResult().remove(existingResult);

            List<OrderMaterialRequirement> MaterialRequirements = currentOp.getMaterialRequirements().stream()
                    .filter(t->!"MP".equals(t.getMaterialTypeName())
                            && t.getProductOrderID() != null && !t.getProductOrderID().isEmpty()
                    )
                    .collect(Collectors.toList());
            if(MaterialRequirements==null||MaterialRequirements.size()==0)
            {
                continue;
            }
            for (OrderMaterialRequirement orderMaterial:MaterialRequirements) {
                List<Integer> orderids= orderMaterial.getProductOrderID();
                if(orderids!=null&&orderids.size()>0) {
                    for (Integer orderid : orderids) {
                        ClearorderOperationResult(chromosome, orderid);
                    }
                }
            }
        }
    }

    public void DelOrder(Chromosome chromosome, int groupid,OrderMaterialRequirement orderMaterialRequirement) {
        List<Entry> allOperations = chromosome.getAllOperations();
        List<GlobalOperationInfo> globalOpList=  chromosome.getGlobalOpList();
        List<Order> orders = chromosome.getOrders();
        List<GAScheduleResult> ScheduleResults = chromosome.getResult();
        Order sourceorder=orders.stream()
                .filter(o -> o.getId()==groupid  )
                .findFirst()
                .orElseThrow(() -> new NoSuchElementException("Order not found: " + groupid));

        List<Entry> sourceOps = allOperations.stream()
                .filter(o -> o.getGroupId()==groupid )
                .sorted(Comparator.comparing(Entry::getSequence))
                .collect(Collectors.toList());
        int GroupId=0;
        chromosome.getReOrderids().add(groupid);



        for (Entry entry : sourceOps) {

            if(!entry.isNewCreate())
            {

                //原有订单不删除
                //entry.setDependentOnOrderIds(new ArrayList<>());
                entry.getTargetFinishedOperationId().remove(orderMaterialRequirement.getOperationId());
                continue;
            }

            orderMaterialRequirement.setProductOrderID(null);


            List<OrderMaterialRequirement> orderMaterialRequirements=  entry.getMaterialRequirements().stream().filter(t-> !"MP".equals(t.getMaterialTypeName())
                    && t.getProductOrderID() != null && !t.getProductOrderID().isEmpty()
            ).collect(Collectors.toList());
            for (OrderMaterialRequirement mr:orderMaterialRequirements) {
                List<Integer> orderids= mr.getProductOrderID();
                if(orderids!=null&&orderids.size()>0) {
                    for (Integer orderid : orderids) {
                        DelOrder(chromosome, orderid,mr);
                    }
                }
            }

            OptionalInt index = IntStream.range(0, allOperations.size())
                    .filter(h -> entry.getId()==allOperations.get(h).getId())
                    .findFirst();
            allOperations.remove((int)index.orElse(0));

            OptionalInt index1 = IntStream.range(0, globalOpList.size())
                    .filter(h -> entry.getId()==globalOpList.get(h).getOp().getId())
                    .findFirst();
            globalOpList.remove((int)index1.orElse(0));

            chromosome.getMachineSelection().remove((int)index1.orElse(0));



            GAScheduleResult result =ScheduleResults.stream()
                    .filter(t -> t.getOperationId()==entry.getId()) // 过滤出值为1的索引
                    .findFirst().orElse(null);

            Long machineId = result.getMachineId();


            Machine machine = chromosome.getMachines().stream()
                    .filter(m -> m.getId() == machineId)
                    .findFirst()
                    .orElse(null);

            AddMachineAvailable(machine,result.getGeneDetails());

            ScheduleResults.remove(result);

        }


        AtomicInteger globalOpId = new AtomicInteger(0);
        globalOpList.forEach(t-> {

            t.setGlobalOpId(globalOpId.getAndIncrement());

        });

        // chromosome.getOperatRel().remove(GroupId-1);
        orders.remove(sourceorder);

    }


    /**
     * 计算在上一工序生产后什么时间可以开工
     * @param details 工序详情列表
     * @param startindex 起始索引
     * @param time2 时间参数2
     * @return 可开工时间
     */
    private int calculateNextOperationStartTime(List<GAScheduleResult> results,List<ScheduleResultDetail> details,  int startindex,  double time2) {
        double qty= results.stream().mapToDouble(GAScheduleResult::getQuantity) // 替换为实际字段名
                .sum();

        double time1 = 0.0;
        for (GAScheduleResult r : results) {
            time1 += 1.0 / r.getOneTime();
        }

        int leadCount =(int) calculateLeadProductionItems(qty, time1, time2);

        if (leadCount == qty) {
            return details.stream()
                    .mapToInt(ScheduleResultDetail::getEndTime)
                    .max()
                    .orElse(0);
        }

        if (startindex > leadCount) {
            leadCount = startindex;
        }
        if(results.size()>1) {//多前置工序
            calculateWithMoreMachine(details, leadCount);
        }
        // 单设备时使用原逻辑
        return (int)calculateWithSingleMachine(details, leadCount, time1);
    }

    /**
     * 计算基于日历重叠约束的开始时间
     * 整合了产能计算和连续性检查
     * @param prevScheduleResults 前一工序的调度结果
     * @param prevDetails 前一工序的详细调度信息
     * @param currentOp 当前工序
     * @param machine 当前工序的目标机器
     * @param processTime 当前工序的处理时间
     * @param prevtime 基础前序时间
     * @return 修正后的开始时间
     */
    private int calculateSSStartTimeWithCalendar(List<GAScheduleResult> prevScheduleResults,
                                                 List<ScheduleResultDetail> prevDetails,
                                                 Entry currentOp, Machine machine,
                                                 double processTime, int prevtime) {
        if (prevScheduleResults == null || prevScheduleResults.isEmpty()) {
            return prevtime;
        }
        //前工序生产数量和

        double qty = prevScheduleResults.stream()
                .mapToDouble(GAScheduleResult::getQuantity)
                .sum();

        if (qty <= 0) {
            return prevtime;
        }


        double totalPrevProcessTime = prevScheduleResults.stream()
                .mapToDouble(r -> r.getOneTime() * r.getQuantity())
                .sum();

        double prevTimePerUnit = totalPrevProcessTime / qty;



        double currentTimePerUnit = processTime;

        //前工序生产多少个后工序可以开工
        int leadCount = (int) calculateLeadProductionItems(qty, prevTimePerUnit, currentTimePerUnit);

        int productionTimeForLeadCount = calculateProductionTimeWithCalendar(
                prevDetails, leadCount, machine, currentOp);

//        int prevEndTime = prevScheduleResults.stream()
//                .mapToInt(GAScheduleResult::getEndTime)
//                .max()
//                .orElse(0);
//
//        int minEndTimeForContinuity = prevEndTime - (int) ((qty - leadCount) * prevTimePerUnit);

        // int adjustedStartTime = Math.max(productionTimeForLeadCount, minEndTimeForContinuity);
        // int  adjustedStartTime = Math.max(productionTimeForLeadCount, prevtime);

        //  int totalProcessingTime = (int) (currentTimePerUnit * qty);
//        int continuityAdjustedTime = ensureContinuousProduction(machine, adjustedStartTime,
//                totalProcessingTime, currentOp);

        return productionTimeForLeadCount; //Math.max(adjustedStartTime, continuityAdjustedTime);
    }
    /**
     * 确保下一工序能够连续生产（不中断）
     * 检查并调整开始时间以保证生产连续性
     */
    private int ensureContinuousProduction(Machine machine, int proposedStartTime,
                                           int processingTime, Entry currentOp) {
        if (machine == null || processingTime <= 0) {
            return proposedStartTime;
        }

        LocalDateTime proposedStart = baseTime.plusSeconds(proposedStartTime);
        LocalDateTime proposedEnd = proposedStart.plusSeconds(processingTime);

        CopyOnWriteArrayList<TimeSegment> availableSegments = machineCalculator.getMachineAvailableTime(
                machine, proposedStartTime, processingTime, null, currentOp.getIsInterrupt() != 1);

        if (availableSegments == null || availableSegments.isEmpty()) {
            return proposedStartTime;
        }

        for (TimeSegment segment : availableSegments) {
            LocalDateTime segStart = segment.getStart();
            LocalDateTime segEnd = segment.getEnd();

            if (!segStart.isAfter(proposedStart) && !segEnd.isBefore(proposedEnd)) {
                return proposedStartTime;
            }

            if (segEnd.isAfter(proposedStart) && segEnd.isBefore(proposedEnd)) {
                int newStartTime = (int) ChronoUnit.SECONDS.between(baseTime, segEnd);
                return ensureContinuousProduction(machine, newStartTime, processingTime, currentOp);
            }

            if (segStart.isAfter(proposedStart) && segStart.isBefore(proposedEnd)) {
                int newStartTime = (int) ChronoUnit.SECONDS.between(baseTime, segStart);
                return newStartTime;
            }
        }

        TimeSegment firstSegment = availableSegments.get(0);
        int segStart = (int) ChronoUnit.SECONDS.between(baseTime, firstSegment.getStart());
        if (segStart > proposedStartTime) {
            return segStart;
        }

        return proposedStartTime;
    }
    /**
     * 根据日历计算生产指定数量所需时间（考虑效率系数）
     */
    private int calculateProductionTimeWithCalendar(List<ScheduleResultDetail> details, int leadCount,
                                                    Machine machine, Entry currentOp) {
        if (details == null || details.isEmpty() || leadCount <= 0) {
            return 0;
        }
        List<ScheduleResultDetail> alldetails=new ArrayList<>();

        for (ScheduleResultDetail detail : details) {
            if(detail.getUsedSegment()!=null&&detail.getUsedSegment().size()>0)
            {
                for (TimeSegment slot: detail.getUsedSegment()) {
                    LocalDateTime startCandidate = slot.getStart();
                    LocalDateTime endCandidate = slot.getEnd();


                    ScheduleResultDetail time = new ScheduleResultDetail();
                    time.setKey(slot.getKey());
                    time.setStartTime((int) ChronoUnit.SECONDS.between(baseTime, startCandidate));
                    time.setEndTime((int) ChronoUnit.SECONDS.between(baseTime, endCandidate));
                    time.setOneTime(detail.getOneTime());
                    alldetails.add(time);
                }
            }else {

                alldetails.add(ProductionDeepCopyUtil.deepCopy(detail));
            }
        }
        alldetails.stream().sorted(Comparator.comparingInt(ScheduleResultDetail::getStartTime));
        int EndTime=0;
        double accumulatedQty = 0.0;
        for (ScheduleResultDetail detail : alldetails) {

            int startTime = detail.getStartTime();
            int endTime = detail.getEndTime();
            //实际可用时长
            double duration = (endTime - startTime)*detail.getEfficiency();

            double cQty=accumulatedQty+duration/ detail.getOneTime();//实际可生产数量
            if(cQty>leadCount)
            {
                double remainingQty = leadCount - accumulatedQty;
                int requiredTime = (int) Math.ceil(remainingQty*detail.getOneTime() / detail.getEfficiency());
                return startTime + requiredTime;
            }else
            {
                accumulatedQty=cQty;
                EndTime=endTime;
            }

        }




        return EndTime;
    }

    /**
     * 多设备并行时计算满足提前量的最早时间
     */
    private int calculateWithParallelMachines(List<ScheduleResultDetail> details, int leadCount, int time1) {
        // 收集所有设备的时间点（开始和结束）并去重排序
        Set<Integer> timePoints = new TreeSet<>();
        for (ScheduleResultDetail detail : details) {
            timePoints.add(detail.getStartTime());
            timePoints.add(detail.getEndTime());
        }
        List<Integer> sortedTimes = new ArrayList<>(timePoints);

        int accumulatedQty = 0;
        int prevTime = 0;

        for (int currTime : sortedTimes) {
            if (prevTime >= currTime) {
                prevTime = currTime;
                continue;
            }
            // 计算当前时间区间[prevTime, currTime)内的有效产能
            int duration = currTime - prevTime;
            int machinesWorking = 0;
            for (ScheduleResultDetail detail : details) {
                // 设备在当前区间内是否处于工作状态
                if (detail.getStartTime() <= prevTime && detail.getEndTime() >= currTime) {
                    machinesWorking++;
                }
            }
            // 区间内的产量（每台设备单位时间产能为1/time1，多设备累加）
            int qtyInInterval = (duration / time1) * machinesWorking;
            accumulatedQty += qtyInInterval;

            // 检查是否满足提前量
            if (accumulatedQty >= leadCount) {
                // 反推精确满足提前量的时间点
                int excess = accumulatedQty - leadCount;
                int timeNeeded = leadCount * time1 - (accumulatedQty - qtyInInterval) * time1;
                return prevTime + timeNeeded;
            }

            prevTime = currTime;
        }

        // 若所有时间点仍未满足，返回最后结束时间
        return details.stream().mapToInt(ScheduleResultDetail::getEndTime).max().orElse(0);
    }
    /**
     * 前置多工序多台，合并时间片段并计算满足前置产量的时间点
     * @param details 排产详情列表（包含开始时间、结束时间、单件工时）
     * @param leadCount 需要提前生产的数量
     * @return 满足前置产量的时间点
     */
    private int calculateWithMoreMachine(List<ScheduleResultDetail> details, int leadCount) {
        if (details == null || details.isEmpty() || leadCount <= 0) {
            return 0; // 边界条件处理
        }

        // 1. 收集所有时间点（开始和结束）并去重排序
        Set<Integer> timePoints = new TreeSet<>();
        for (ScheduleResultDetail detail : details) {
            timePoints.add(detail.getStartTime());
            timePoints.add(detail.getEndTime());
        }
        List<Integer> sortedTimes = new ArrayList<>(timePoints);
        if (sortedTimes.size() < 2) {
            return details.get(0).getEndTime(); // 无有效时间片段
        }

        // 2. 按时间片段计算累计产量
        double accumulatedQty = 0.0;
        for (int i = 0; i < sortedTimes.size() - 1; i++) {
            int startTime = sortedTimes.get(i);
            int endTime = sortedTimes.get(i + 1);
            int duration = endTime - startTime;
            if (duration <= 0) {
                continue; // 跳过无效时间段
            }

            // 计算当前时间段内所有运行的设备总效率（件/单位时间）
            //1秒生产的数量
            double totalEfficiency = details.stream()
                    .filter(detail -> detail.getStartTime() <= startTime
                            && detail.getEndTime() >= endTime)
                    .mapToDouble(detail -> 1.0 / detail.getOneTime()) // 单件工时的倒数即效率
                    .sum();

            // 当前时间段可生产的数量
            double segmentQty = totalEfficiency * duration;

            // 检查是否在当前时间段内满足前置产量
            if (accumulatedQty + segmentQty >= leadCount) {
                // 计算精确时间点（向上取整避免小数精度问题）
                double remainingQty = leadCount - accumulatedQty;
                int requiredTime = (int) Math.ceil(remainingQty / totalEfficiency);//数量除以每秒的数量，  每秒生产多少个，生产X用几秒
                return startTime + requiredTime;
            }

            accumulatedQty += segmentQty;
        }

        // 3. 所有片段累计仍未满足（返回最后结束时间）
        return details.stream()
                .mapToInt(ScheduleResultDetail::getEndTime)
                .max()
                .orElse(0);
    }

    /**
     * 单设备时使用原逻辑（保持兼容）
     */
    private double calculateWithSingleMachine(List<ScheduleResultDetail> details, int leadCount, double time1) {
        //上一工序的排产详情 - 需要提前生产出来的数量花费的时间
        double alltime = leadCount * time1;
        for (ScheduleResultDetail detail : details) {
            double time3 = alltime - detail.getProcessingTime();
            if (time3 < 0) {
                return detail.getEndTime() + time3;
            } else if (time3 == 0) {
                return detail.getEndTime();
            } else {
                alltime = time3;
            }
        }
        return details.get(details.size() - 1).getEndTime();
    }
    /**
     * 计算工序1需要提前生产的件数
     * @param qty 总订单量
     * @param time1 工序1单件工时
     * @param time2 工序2单件工时
     * @return 工序1需要提前生产的件数
     */
    private double calculateLeadProductionItems(double qty, double time1, double time2) {
        if (time1 <= time2) {
            return 1;
        }
        if (qty <= 0 || time1 <= 0 || time2 <= 0) {
            throw new IllegalArgumentException("参数必须为正整数");
        }
        double totalTime1 = qty * time1;
        double totalTime2 = qty * time2;
        double timeDifference =0-( totalTime2 - totalTime1);

        return (timeDifference / time1) > qty ? qty : (timeDifference / time1);
    }
    private String ConvertTime(int minute) {
        return baseTime.plusSeconds(minute).format(java.time.format.DateTimeFormatter.ofPattern("YYYY-MM-dd HH:mm"));
    }
    private Map<Integer,Object> calculateSetupTime(GAScheduleResult  lastGeneOnMachine, Entry operation, Machine machine, int earliestStartTime,int processingTimeTotal,boolean changeOverInWeek,List<Entry> allOperations) {

        Map<Integer,Object> reslte=new HashMap<>();
        reslte.put(1,0);//换型时间
        reslte.put(2,0);//换型开始时间
        reslte.put(3,0);//上个任务的结束时间
        reslte.put(4,earliestStartTime);//最早开工时间
        reslte.put(5,processingTimeTotal);//总加工时长
        if(lastGeneOnMachine==null)
        {
            return reslte;
        }
        // LocalDateTime startTime = baseTime.plus(earliestStartTime, ChronoUnit.SECONDS);




        reslte.put(3,lastGeneOnMachine.getEndTime());//换型开始时间
        String ExecId=lastGeneOnMachine.getExecId();

        Entry prev= allOperations.stream().
                filter(t->t.getExecId().equals(ExecId))
                .findFirst().orElse(null);
        int setupTime=0;
        if(prev!=null)
        {
            //离散参数
            //  prev.getDiscreteParameter()

//            setupTime = (prev.getProductId() != operation.getProductId())
//                    ? (int) discreteParameterMatrixService.getDiscreteParameterMatrixValue(prev, operation)
//                    : 0;
            DiscreteParameterMatrixService discreteParameterMatrixService = SpringContextUtil.getBean(DiscreteParameterMatrixService.class);
            DiscreteParameterDurationService discreteParameterDurationService = SpringContextUtil.getBean(DiscreteParameterDurationService.class);


            double discreteParameterDurationValue = discreteParameterDurationService.calculateChangeoverTime(prev, operation, machine, allOperations, earliestStartTime,null);
            double discreteParameterMatrixValue = discreteParameterMatrixService.getDiscreteParameterMatrixValue(operation, prev);
            setupTime = (int) Math.max(discreteParameterDurationValue, discreteParameterMatrixValue);
//                setupTime = (int) discreteParameterMatrixValue;



//                System.out.println("换型时间"+discreteParameterMatrixValue);
//                System.out.println(setupTime+"换型时间"+"huanxingshijian ");


        }

        //  setupTime=20*3600;
        operation.setChangeLineTime(setupTime);

        reslte.put(1,setupTime);//换型时间
        if(changeOverInWeek)//可以放到休息时间
        {

            CopyOnWriteArrayList<TimeSegment> AvailableTimeSegment = machineCalculator.getMachineAvailableTime(machine, earliestStartTime+setupTime,
                    processingTimeTotal, null, operation.getIsInterrupt()!=1);

            if(AvailableTimeSegment!=null) {
                reslte.put(6, AvailableTimeSegment);
                int start = (int) ChronoUnit.SECONDS.between(baseTime, AvailableTimeSegment.get(0).getStart());

                earliestStartTime = earliestStartTime > start ? earliestStartTime : start;

                reslte.put(4, earliestStartTime);//最早开工时间
                reslte.put(2,earliestStartTime-setupTime);//换型开始时间
            }


            //01 16:00 +20 -01 16:00  02 12:00  08:00 -18:00  01 16:18 02 08:00-12:00
            //01 16:00 +10 -01 16:00  换型10：00  08:00
            //01 18:00 +10 -02 08:00<0 换型 休息时间满足
            //01 18:00 +20 -02 08:00>0
            //01 18:00 +10 -02 00:00>0
            return reslte;
        }else {
            //开始时间加上设置时间重新算
            //如果是前提供任务是相同的则跳出

            CopyOnWriteArrayList<TimeSegment> AvailableTimeSegment = machineCalculator.getMachineAvailableTime(machine, earliestStartTime,
                    processingTimeTotal+setupTime, null, operation.getIsInterrupt()!=1);

            if(AvailableTimeSegment!=null) {
                reslte.put(6, AvailableTimeSegment);
                int start = (int) ChronoUnit.SECONDS.between(baseTime, AvailableTimeSegment.get(0).getStart());

                earliestStartTime = earliestStartTime > start ? earliestStartTime : start;

                reslte.put(4, earliestStartTime);//最早开工时间
                reslte.put(2,earliestStartTime);//换型开始时间
                reslte.put(5,processingTimeTotal+setupTime);//换型开始时间
            }
        }



//        System.out.println("换型时间111"+setupTime);

        return reslte;
    }

    private Map<Integer,Object> calculateSetupTime1(CopyOnWriteArrayList<GAScheduleResult> machineTasks, Entry operation, Machine machine, int earliestStartTime,int processingTimeTotal,boolean changeOverInWeek,String lastExecId,Map<Integer,Object> lastsetupTime) {

        Map<Integer,Object> reslte=new HashMap<>();
        reslte.put(1,0);//换型时间
        reslte.put(2,0);//换型开始时间
        reslte.put(3,0);//上个任务的结束时间
        reslte.put(4,earliestStartTime);//最早开工时间
        reslte.put(5,processingTimeTotal);//总加工时长
        if(machineTasks==null||machineTasks.size()==0)
        {
            return reslte;
        }
        // LocalDateTime startTime = baseTime.plus(earliestStartTime, ChronoUnit.SECONDS);

        GAScheduleResult  lastGeneOnMachine=machineTasks.get(machineTasks.size()-1);




        if(lastGeneOnMachine.getEndTime()>earliestStartTime)
        {
            CopyOnWriteArrayList<TimeSegment> AvailableTimeSegment = machineCalculator.getMachineAvailableTime(machine, earliestStartTime,
                    processingTimeTotal, machineTasks, operation.getIsInterrupt()!=1);

            if(AvailableTimeSegment!=null) {
                reslte.put(6,AvailableTimeSegment);
                int start=  (int) ChronoUnit.SECONDS.between(baseTime, AvailableTimeSegment.get(0).getStart());

                earliestStartTime= earliestStartTime>start  ?earliestStartTime:start;
                int earliestStartTime1=earliestStartTime;
                reslte.put(4,earliestStartTime);//最早开工时间
                CopyOnWriteArrayList<GAScheduleResult> machineTasks1=  machineTasks.stream()
                        .filter(t->t.getEndTime()<=earliestStartTime1)
                        .collect(Collectors.toCollection(CopyOnWriteArrayList::new));
                if(machineTasks1!=null&&machineTasks1.size()>0)
                {
                    lastGeneOnMachine=machineTasks1.get(machineTasks1.size()-1);
                }else {

                    return reslte;
                }
            }
        }else {
            CopyOnWriteArrayList<TimeSegment> AvailableTimeSegment = machineCalculator.getMachineAvailableTime(machine, earliestStartTime,
                    processingTimeTotal, machineTasks, operation.getIsInterrupt()!=1);
            if(AvailableTimeSegment!=null) {
                reslte.put(6, AvailableTimeSegment);
                int start = (int) ChronoUnit.SECONDS.between(baseTime, AvailableTimeSegment.get(0).getStart());

                earliestStartTime = earliestStartTime > start ? earliestStartTime : start;

                reslte.put(4,earliestStartTime);//最早开工时间
            }
        }

        reslte.put(3,lastGeneOnMachine.getEndTime());//换型开始时间
        String ExecId=lastGeneOnMachine.getExecId();

        if(lastExecId.equals(ExecId)) {
            reslte.put(1, lastsetupTime.get(1));//换型时间
            if(changeOverInWeek) {
                reslte.put(2, earliestStartTime - (int) lastsetupTime.get(1)-1);
            }
            return reslte;

        }

        Entry prev= _allOperations.stream().
                filter(t->t.getExecId().equals(ExecId))
                .findFirst().orElse(null);
        int setupTime=0;
        if(prev!=null)
        {
            //离散参数
            //  prev.getDiscreteParameter()

//            setupTime = (prev.getProductId() != operation.getProductId())
//                    ? (int) discreteParameterMatrixService.getDiscreteParameterMatrixValue(prev, operation)
//                    : 0;
            DiscreteParameterMatrixService discreteParameterMatrixService = SpringContextUtil.getBean(DiscreteParameterMatrixService.class);
            DiscreteParameterDurationService discreteParameterDurationService = SpringContextUtil.getBean(DiscreteParameterDurationService.class);


            double discreteParameterDurationValue = discreteParameterDurationService.calculateChangeoverTime(prev, operation, machine, _allOperations, earliestStartTime,machineTasks);
            double discreteParameterMatrixValue = discreteParameterMatrixService.getDiscreteParameterMatrixValue(operation, prev);
            setupTime = (int) Math.max(discreteParameterDurationValue, discreteParameterMatrixValue);
//                setupTime = (int) discreteParameterMatrixValue;



//                System.out.println("换型时间"+discreteParameterMatrixValue);
//                System.out.println(setupTime+"换型时间"+"huanxingshijian ");


        }

        //  setupTime=20*3600;
        operation.setChangeLineTime(setupTime);
        if(setupTime==0)
        {
            return reslte;
        }
        reslte.put(1,setupTime);//换型时间
        if(changeOverInWeek)//可以放到休息时间
        {
            //01 16:00 +20 -01 16:00  02 12:00  08:00 -18:00  01 16:18 02 08:00-12:00
            //01 16:00 +10 -01 16:00  换型10：00  08:00
            //01 18:00 +10 -02 08:00<0 换型 休息时间满足
            //01 18:00 +20 -02 08:00>0
            //01 18:00 +10 -02 00:00>0
            int cha=(lastGeneOnMachine.getEndTime()+setupTime)-earliestStartTime;
            if(cha>0)
            {
                cha=cha+1;//加1是工序开始加工时间
                reslte.put(2,lastGeneOnMachine.getEndTime());//换型开始时间
                //  reslte = calculateSetupTime(machineTasks, operation, machine,earliestStartTime+cha,processingTimeTotal, _globalParam.is_smoothChangeOverInWeek(), ExecId,reslte);

            }
            else {
                reslte.put(2,earliestStartTime-setupTime);//换型开始时间
                //如果空余时间足够
                //可能会往前或后暂用设备时间
                return reslte;
            }
        }else {
            //开始时间加上设置时间重新算
            //如果是前提供任务是相同的则跳出

            // reslte = calculateSetupTime(machineTasks, operation, machine,earliestStartTime,processingTimeTotal+setupTime, _globalParam.is_smoothChangeOverInWeek(),ExecId,reslte);

        }

//        System.out.println("换型时间111"+setupTime);

        return reslte;
    }

    // 释放试排阶段占用的机台 availability 段，避免临时状态污染下一轮排程/BOM 试算。
    public void AddMachineAvailable(Machine machine, List<ScheduleResultDetail> geneDetails) {
        if (geneDetails == null || geneDetails.isEmpty()) return;

        List<String> keys=  geneDetails.stream().
                filter(t->t.getUsedSegment()==null||t.getUsedSegment().size()==0)
                .map(ScheduleResultDetail::getKey)
                .collect(Collectors.toList());

        List<String> keys1= geneDetails.stream().
                filter(t->t.getUsedSegment()!=null)
                .flatMap(detail -> detail.getUsedSegment().stream())
                .map(TimeSegment::getKey).collect(Collectors.toList());
        if(keys1!=null&&keys1.size()>0) {
            keys.addAll(keys1);
        }

        List<TimeSegment> toUpdate = machine.getAvailability().stream()
                .filter(t -> keys.contains(t.getKey()))
                .collect(Collectors.toList());

// 然后批量修改
        toUpdate.forEach(t -> t.setUsed(false));



    }



    private void calculateScheduleResult(Chromosome chromosome) {
        double[] Objectives = new double[_globalParam.getObjectiveWeights().size()];
        double[] weights = new double[_globalParam.getObjectiveWeights().size()];

        int i = 0;
        for (ObjectiveConfig config : _globalParam.getObjectiveConfigs()) {
            if (config.isEnabled()) {
                if (GlobalParam.OBJECTIVE_MAKESPAN.equals(config.getName())) {
                    // 1. 最早完工时间（最小化）
                    double makespan = chromosome.getResult().stream()
                            .mapToInt(GAScheduleResult::getEndTime)
                            .max()
                            .orElse(0);
                    Objectives[i] = makespan;
                    weights[i] = config.getWeight();
                    chromosome.setMakespan(makespan);

                }
                if (GlobalParam.OBJECTIVE_TARDINESS.equals(config.getName())) {
                    // 2. 交付期满足情况（最小化延迟）
                    double tardiness = 0;

                    Map<Integer, List<GAScheduleResult>> orderGroups = chromosome.getResult().stream()
                            .collect(Collectors.groupingBy(GAScheduleResult::getGroupId));

                    for (Map.Entry<Integer, List<GAScheduleResult>> group : orderGroups.entrySet()) {
                        int groupId = group.getKey();
                        int orderCompletion = group.getValue().stream()
                                .mapToInt(GAScheduleResult::getEndTime)
                                .max()
                                .orElse(0);
                        List<String> orderIds = group.getValue().stream()
                                .map(GAScheduleResult::getOrderId)
                                .distinct()
                                .sorted()
                                .collect(Collectors.toList());
                        Order order = chromosome.getOrders().stream()
                                .filter(t -> orderIds.contains(t.getOrderId()))
                                .max(Comparator.comparing(Order::getDueDate))
                                .orElse(null);
                        if (order.isNewSfCreate()) {
                            continue;
                        }
                        LocalDateTime dueDateTime = order.getDueDate();


                        LocalDateTime completionTime = baseTime.plusSeconds(orderCompletion);


                        if (completionTime.isAfter(dueDateTime)) {
                            // 计算延迟小时数（修复时间计算）
                            long hours = ChronoUnit.HOURS.between(dueDateTime, completionTime);
                            long minutes = ChronoUnit.MINUTES.between(dueDateTime, completionTime) % 60;
                            tardiness += hours * 60 + (double) minutes;
                        }

                    }

                    Objectives[i] = tardiness;
                    chromosome.setDelayTime(tardiness);
                }
                if (GlobalParam.OBJECTIVE_SETUP_TIME.equals(config.getName())) {
                    // 3. 最小总换型时间
                    double totalSetupTime = calculateTotalSetupTime(chromosome);
                    chromosome.setTotalChangeoverTime(totalSetupTime);
                    Objectives[i] = totalSetupTime;

                }
                if (GlobalParam.OBJECTIVE_FLOW_TIME.equals(config.getName())) {
                    // 4. 最小化总流程时间 所有工序加工时间的总和
                    double totalFlowTime = calculateTotalFlowTime(chromosome);
                    chromosome.setTotalFlowTime(totalFlowTime);
                    Objectives[i] = totalFlowTime;
                }
                if (GlobalParam.OBJECTIVE_MACHINE_LOAD.equals(config.getName())) {
                    // 5. 机器负载均衡
                    double machineLoadBalance = calculateMachineLoadBalance(chromosome);
                    chromosome.setMachineLoadStd(machineLoadBalance);
                    Objectives[i] = machineLoadBalance;
                }
                i++;
            }
        }

        chromosome.setObjectives(Objectives);

        // 计算各 KPI 的理论下界（用于计算 Gap = (current - lowerBound) / lowerBound）
        try {
            KpiLowerBoundCalculator.computeAndSetLowerBounds(chromosome, _globalParam);
        } catch (Exception e) {
            // 下界计算异常不应影响主流程
            com.aps.common.util.FileHelper.writeLogFile(
                    "KPI 下界计算异常: " + e.getClass().getSimpleName() + " - " + e.getMessage());
        }

        FitnessCalculator fitnessCalculator = new FitnessCalculator();

        chromosome.setFitnessLevel(fitnessCalculator.calculateFitness(chromosome, _globalParam));

    }

    private double calculateTotalFlowTime(Chromosome chromosome) {
        return chromosome.getResult().stream()
                .mapToDouble(GAScheduleResult::getFlowTime)
                .sum();
    }



    // 计算总换型时间
    private double calculateTotalSetupTime(Chromosome chromosome) {
        return chromosome.getResult().stream()
                .mapToDouble(GAScheduleResult::getChangeOverTime)
                .sum();
    }

    // 计算机器负载均衡指标
    private double calculateMachineLoadBalance(Chromosome chromosome) {
        Map<Long, Double> machineUtilization = new HashMap<>();
        int sumWork = chromosome.getResult().stream()
                .mapToInt(GAScheduleResult::getFlowTime)
                .sum();//总的加工时间


        if (sumWork == 0) return 0;

        for (Machine machine : chromosome.getMachines()) {
            double busyTime = chromosome.getResult().stream()
                    .filter(g -> g.getMachineId() == machine.getId())
                    .mapToInt(g -> g.getFlowTime())
                    .sum();



            machineUtilization.put(machine.getId(), busyTime / sumWork);
        }

        double avgUtilization = machineUtilization.values().stream()
                .mapToDouble(Double::doubleValue)
                .sum()/ chromosome.getMachines().size();

        double variance = machineUtilization.values().stream()
                .mapToDouble(u -> Math.pow(u - avgUtilization, 2))
                .sum() / chromosome.getMachines().size();

        // 标准差与平均值的比值衡量负载离散程度，值越小说明均衡度越高
        return Math.sqrt(variance)/avgUtilization ;
    }

    /**
     * 补全：创建缓存键（核心逻辑，需与原 C# CreateCacheKey 一致）
     * 思路：将染色体的核心特征（机器选择+工序排序）拼接为字符串，确保相同染色体生成相同键
     */
    private String createCacheKey(Chromosome chromosome) {

        return  chromosome.getGeneStr();

        // 拼接机器选择：用 "," 分隔（例：1,3,2,4）
        // String machineStr = chromosome.getMachineStr();

        // 拼接工序排序：用 "|" 分隔（例：2|1|3|4）
        //  String operationStr = chromosome.getOperationStr();

        // 组合最终键（用 "_" 分隔两部分，避免冲突）
        //   return machineStr + "_" + operationStr;
    }

    public void DelOrder(Chromosome chromosome) {
        List<Entry> allOperations = chromosome.getAllOperations();
        List<GlobalOperationInfo> globalOpList=  chromosome.getGlobalOpList();
        if(chromosome.getOrders()==null||chromosome.getOrders().size()==0)
            return;
        List<Order> orders = chromosome.getOrders();
        List<Integer> OperationSequencing=  chromosome.getOperationSequencing();
        List<Integer> newoorderids= orders.stream()
                .filter(t->t.isNewSfCreate())
                .map(Order::getId)
                .sorted(Comparator.reverseOrder())
                .collect(Collectors.toList());
        if(newoorderids!=null&&newoorderids.size()>0) {
            for (Integer id : newoorderids) {


                List<Entry> sourceOps = allOperations.stream()
                        .filter(o -> o.getGroupId()==id)
                        .sorted(Comparator.comparing(Entry::getSequence))
                        .collect(Collectors.toList());

                for (Entry entry : sourceOps) {
                    OptionalInt index1 = IntStream.range(0, globalOpList.size())
                            .filter(h -> entry.getId()==globalOpList.get(h).getOp().getId())
                            .findFirst();
                    globalOpList.remove((int)index1.orElse(0));

                    chromosome.getMachineSelection().remove((int)index1.orElse(0));
                }

                chromosome.getOperatRel().remove(id-1);

            }
            allOperations.removeIf(t ->newoorderids.contains(t.getGroupId()));
            OperationSequencing.removeIf(t ->newoorderids.contains(t));
            AtomicInteger globalOpId = new AtomicInteger(0);
            globalOpList.forEach(t-> {

                t.setGlobalOpId(globalOpId.getAndIncrement());

            });
            orders.removeIf(t ->newoorderids.contains(t.getId()));
        }
    }
    private void reForwardFinishedOrders(int semiOrderId,int forwardEndTime,
                                         Set<Integer> reForwardFinishedOrderIds,
                                         Chromosome chromosome,
                                         Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,
                                         Map<Integer, GAScheduleResult> scheduleIndexById,
                                         Map<Long, Machine> machineIdMap,
                                         Map<Integer, Entry> entryIndexById,
                                         Map<String, OpMachine> opMachineKeyMap,
                                         Map<Integer, List<Entry>> entrysBygroupId,
                                         Map<Integer, Integer> orderProcessCounter,
                                         Map<Integer, Integer> orderLastEndTime,
                                         Set<Integer> forwardFallbackOrderIds,
                                         Map<Integer, AbstractMap.SimpleEntry<Boolean, Integer>> orderSchedulingInfo) {
        for (int finishedId : reForwardFinishedOrderIds) {
            int scheduledCount = orderProcessCounter.getOrDefault(finishedId, 0);
            if (scheduledCount == 0) {
                continue;
            }
            List<Integer> removeOp =  clearOrderSchedulingForForwardFallback(chromosome, finishedId,
                    machineTasksCache, scheduleIndexById,entryIndexById,null);

            int forwardEndTime1 = scheduleOrderForwardFallback(finishedId,removeOp,forwardEndTime,
                    chromosome,entrysBygroupId, machineIdMap, machineTasksCache,
                    entryIndexById, scheduleIndexById, opMachineKeyMap);

            orderProcessCounter.put(finishedId,
                    entrysBygroupId.get(finishedId).size());
            orderLastEndTime.put(finishedId, forwardEndTime1);
            forwardFallbackOrderIds.add(finishedId);
            orderSchedulingInfo.put(finishedId,
                    new AbstractMap.SimpleEntry<>(false, 0));
//            FileHelper.writeLogFile("[ReForward] 半成品" + semiOrderId
//                    + "倒排早于基准时间，成品" + finishedId + "重新正排，结束时间=" + forwardEndTime);
        }
        reForwardFinishedOrderIds.clear();
    }

    /**
     * 物料扣减记录：区分库存扣减(useStock)和在途扣减(useTransit)
     */
    private static class MaterialDeduction {
        double useStock;   // 占用库存（回滚时还原到 materialStocks）
        double useTransit; // 占用在途（回滚时还原到 InTransit）
    }

    // 读工序扣减的库存记录：materialId → 扣减明细（含库存 + 在途 + 替换料）
    private Map<String, MaterialDeduction> readOperationStockDeductions(Entry op) {
        Map<String, MaterialDeduction> result = new HashMap<>();
        List<OrderMaterialRequirement> requirements = op.getMaterialRequirements();
        if (requirements != null) {
            for (OrderMaterialRequirement req : requirements) {
                // 替换料

                double replaceStock=0;
                double replaceTransit=0;

                List<OrderMaterialRequirement> replaceMaterials = req.getReplaceMaterial();
                if (replaceMaterials != null) {
                    for (OrderMaterialRequirement rep : replaceMaterials) {
                        replaceStock+=rep.getUseStock();
                        replaceTransit+=rep.getUseTransit();
                        mergeRequirementIntoDeduction(result, rep,0,0);
                    }
                }
                mergeRequirementIntoDeduction(result, req,replaceStock,replaceTransit);

            }
        }
        return result;
    }

    private void mergeRequirementIntoDeduction(Map<String, MaterialDeduction> map,
                                               OrderMaterialRequirement req,double replaceStock,double replaceTransit) {
        double useStock = req.getUseStock()-replaceStock;
        double useTransit = req.getUseTransit()-replaceTransit;
        if (useStock <= 0 && useTransit <= 0) return;
        MaterialDeduction ded = map.computeIfAbsent(req.getMaterialId(),
                k -> new MaterialDeduction());
        ded.useStock += useStock;
        ded.useTransit += useTransit;
    }

    // 回滚已扣库存（含库存 + 在途）
    private void rollbackOperationStockDeduction(Chromosome chromosome,
                                                 Map<String, MaterialDeduction> deductions) {
        TreeMap<String, Material> materials = chromosome.getMaterials();
        for (Map.Entry<String, MaterialDeduction> entry : deductions.entrySet()) {
            String materialId = entry.getKey();
            MaterialDeduction deduction = entry.getValue();
            Material material = materials.get(materialId);
            if (material == null) continue;

            // 回滚库存：还原 materialStocks.usedInventory
            if (deduction.useStock > 0) {
                List<Stock> stocks = material.getMaterialStocks().stream()
                        .filter(t -> t.getUsedInventory() > 0)
                        .collect(Collectors.toList());
                double remaining = deduction.useStock;
                for (Stock s : stocks) {
                    double rollback1 = Math.min(remaining, s.getUsedInventory());
                    s.setUsedInventory(s.getUsedInventory() - rollback1);
                    remaining -= rollback1;
                    if (remaining <= 0) break;
                }
                if (remaining > 0) {
                    FileHelper.writeLogFile("[StockRollback] 物料" + material.getCode()
                            + " 库存回滚不足，剩余=" + remaining);
                }
            }

            // 回滚在途：还原 InTransit(MaterialSupply).Quantity
            if (deduction.useTransit > 0) {
                List<MaterialSupply> inTransit = material.getInTransit();
                if (inTransit != null && !inTransit.isEmpty()) {
                    // 按到货时间顺序回滚（先到先回滚）
                    List<MaterialSupply> sorted = inTransit.stream()
                            .sorted(Comparator.comparing(MaterialSupply::getArrivalTime,
                                    Comparator.nullsLast(Comparator.naturalOrder())))
                            .collect(Collectors.toList());
                    double remaining = deduction.useTransit;
                    for (MaterialSupply supply : sorted) {
                        double rollback1 = remaining;
                        supply.setQuantity(supply.getQuantity() + rollback1);
                        remaining -= rollback1;
                        if (remaining <= 0) break;
                    }
                    if (remaining > 0) {
                        FileHelper.writeLogFile("[StockRollback] 物料" + material.getCode()
                                + " 在途回滚不足，剩余=" + remaining);
                    }
                } else {
                    FileHelper.writeLogFile("[StockRollback] 物料" + material.getCode()
                            + " 在途列表为空，无法回滚 useTransit=" + deduction.useTransit);
                }
            }
        }
    }

}
