package com.aps.service.plan;



import com.aps.common.util.FileHelper;
import com.aps.entity.basic.*;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

public class AlgorithmScheduler6 {
    private final List<Product> _products;
    private final List<Machine> _machines;
    private final List<Order> _orders;
    private final Random _random;
    private final MachineSchedulerService _machineScheduler;
    private int _populationSize = 100;
    private double _crossoverRate = 0.8;
    private double _mutationRate = 0.1;
    private int _maxGenerations = 500;
    private int _elitismCount = 5;
    private final LocalDateTime baseTime = LocalDateTime.of(2025, 10, 1, 0, 0, 0);

    public AlgorithmScheduler6(List<Product> products, List<Machine> machines, List<Order> orders, MachineSchedulerService machineScheduler) {
        this._products = deepCopyProductList(products);
        this._machines = deepCopyMachineList(machines);
        this._orders = deepCopyOrderList(orders);
        this._machineScheduler = machineScheduler;
        this._random = new Random();
    }

    public ScheduleChromosome Run() {
        List<ScheduleChromosome> population = InitializePopulation();
        ScheduleChromosome bestSolution = null;
        ScheduleChromosome currentBest = null;
        double bestFitness = Double.MIN_VALUE;

        currentBest = population.stream()
                .max(Comparator.comparingDouble(ScheduleChromosome::getFitness))
                .orElse(null);

        if (currentBest != null) {
            bestFitness = currentBest.getFitness();
            bestSolution = deepCopyScheduleChromosome(currentBest);
        }

        return bestSolution;
    }

    public List<ScheduleChromosome> RunAll() {
        return InitializePopulation();
    }

    private List<ScheduleChromosome> InitializePopulation() {
        List<ScheduleChromosome> population = new ArrayList<>();

        System.out.println("开始初始化种群，目标大小: " + _populationSize);

        for (int i = 0; i < _populationSize; i++) {
            ScheduleChromosome chromosome = new ScheduleChromosome(baseTime);
            chromosome.setGenes(new ArrayList<>());
            chromosome.setObjectiveValues(new HashMap<>());
            chromosome.setOrders(deepCopyOrderList(_orders));
            chromosome.setMachines(deepCopyMachineList(_machines));

            // 为每个订单分配工序
            for (Order order : _orders) {
                Product product = _products.stream()
                        .filter(p -> p.getId() == order.getProductId())
                        .findFirst()
                        .orElseThrow(() -> new NoSuchElementException("Product not found: " + order.getProductId()));

                int prevtime = 0;
                int remainingQuantity = order.getQuantity();

                // 订单拆分逻辑 - 增强随机性
                while (remainingQuantity > 0) {
                    int batchSize;
                    if (order.isCanSplit() && remainingQuantity > 1) {
                        // 修改：增强批次拆分的随机性
                        int maxSplit = Math.min(remainingQuantity, Math.max(1, remainingQuantity / 2));
                        batchSize = _random.nextInt(maxSplit) + 1;
                    } else {
                        batchSize = remainingQuantity;
                    }
                    if (batchSize > remainingQuantity) {
                        batchSize = remainingQuantity;
                    }
                    remainingQuantity -= batchSize;

                    // 按工序顺序处理
                    for (Operation operation : product.getOperations().stream()
                            .sorted(Comparator.comparingInt(Operation::getSequence))
                            .collect(Collectors.toList())) {

                        if (operation.getId() > 1) {
                            Gene prevGene = chromosome.getGenes().stream()
                                    .filter(t -> t.getOrderId() == order.getId() && t.getOperationId() == operation.getId() - 1)
                                    .findFirst()
                                    .orElse(null);
                            prevtime = prevGene != null ? prevGene.getEndTime() : 0;
                        }

                        MachineOption machineOption;
                        Machine machine;

                        // 多设备选择逻辑 - 增强随机性
                        if (operation.getMachineOptions().size() > 1) {
                            Set<Integer> machineIds = operation.getMachineOptions().stream()
                                    .map(MachineOption::getMachineId)
                                    .collect(Collectors.toSet());

                            // 修改：增强设备选择的随机性
                            List<Machine> availableMachines = chromosome.getMachines().stream()
                                    .filter(t -> machineIds.contains(t.getId()))
                                    .collect(Collectors.toList());

                            if (!availableMachines.isEmpty()) {
                                // 随机打乱后选择
                                Collections.shuffle(availableMachines, _random);
                                machine = availableMachines.get(0);

                                Machine finalMachine = machine;
                                machineOption = operation.getMachineOptions().stream()
                                        .filter(t -> t.getMachineId() == finalMachine.getId())
                                        .findFirst()
                                        .orElseThrow(() -> new NoSuchElementException("MachineOption not found for machine: " + finalMachine.getId()));
                            } else {
                                // 回退到原始逻辑
                                machine = chromosome.getMachines().stream()
                                        .filter(t -> machineIds.contains(t.getId()))
                                        .sorted(Comparator.comparingInt(Machine::getEarliestTime)
                                                .thenComparingInt(Machine::getTotalTaskTime)
                                                .thenComparing(t -> _random.nextDouble()))
                                        .findFirst()
                                        .orElseThrow(() -> new NoSuchElementException("No available machine for operation: " + operation.getId()));

                                Machine finalMachine = machine;
                                machineOption = operation.getMachineOptions().stream()
                                        .filter(t -> t.getMachineId() == finalMachine.getId())
                                        .findFirst()
                                        .orElseThrow(() -> new NoSuchElementException("MachineOption not found for machine: " + finalMachine.getId()));
                            }
                        } else {
                            machineOption = operation.getMachineOptions().get(0);
                            MachineOption finalMachineOption = machineOption;
                            machine = chromosome.getMachines().stream()
                                    .filter(m -> m.getId() == finalMachineOption.getMachineId())
                                    .findFirst()
                                    .orElseThrow(() -> new NoSuchElementException("Machine not found: " + finalMachineOption.getMachineId()));
                        }

                        int processingTime = machineOption.getProcessingTime() * batchSize;
                        int preTime = machineOption.getPreTime(); // 前处理时间(常数时间，与批次大小无关)
                        int setupTime = 0; // 换型时间默认为0，仅在产品变化时计算
                        int teardownTime = machineOption.getTeardownTime(); // 后处理时间(常数时间，与批次大小无关)

                        // 计算换型时间
                        // 查找该机器上一个任务
                        Gene lastGeneOnMachine = chromosome.getGenes().stream()
                                .filter(g -> g.getMachineId() == machine.getId())
                                .max(Comparator.comparingInt(Gene::getEndTime))
                                .orElse(null);

                        // 如果上一个任务的产品与当前任务不同，则需要换型时间
                        if (lastGeneOnMachine != null && lastGeneOnMachine.getProductId() != order.getProductId()) {
                            setupTime = machineOption.getSetupTime();
                        }
                        // 前处理时间可以在上一个工序未完成时开始，所以调整开始时间
                        int adjustedPrevTime = prevtime;
                        if (preTime > 0 && lastGeneOnMachine != null) {
                            // 前处理可以在上一个任务结束前preTime时间开始
                            adjustedPrevTime = lastGeneOnMachine.getEndTime() - preTime;
                        }

//                        List<GeneDetail> geneDetails = GetNextAvailableTime(
//                                machine, prevtime, -1, processingTime,
//                                chromosome.getGenes(), false, true
//                        );


                        List<GeneDetail> geneDetails = GetNextAvailableTime(
                                machine, adjustedPrevTime, -1, processingTime + teardownTime + setupTime,
                                chromosome.getGenes(), false, true
                        );

                        int startTime = geneDetails.stream().mapToInt(GeneDetail::getStartTime).min().orElse(0);
                        int endTime = geneDetails.stream().mapToInt(GeneDetail::getEndTime).max().orElse(0);

                        machine.setEarliestTime(endTime);
                        machine.setTotalTaskTime(machine.getTotalTaskTime() + +teardownTime + setupTime);

                        Gene gene = new Gene();
                        gene.setOrderId(order.getId());
                        gene.setProductId(order.getProductId());
                        gene.setOperationId(operation.getId());
                        gene.setMachineId(machineOption.getMachineId());
                        gene.setBatchSize(batchSize);
                        gene.setStartTime(startTime);
                        gene.setEndTime(endTime);
                        gene.setProcessingTime(processingTime);
                        gene.setGeneDetails(deepCopyGeneDetailList(geneDetails));
                        gene.setId(chromosome.getGenes().size() + 1);
                        gene.setSequenceId(operation.getSequence());
                        chromosome.getGenes().add(gene);
                    }
                }
            }

            population.add(chromosome);
        }

        System.out.println("生成种群大小: " + population.size());

        Map<String, List<ScheduleChromosome>> grouped = population.stream()
                .collect(Collectors.groupingBy(ScheduleChromosome::getGenesStr));

        population = grouped.values().stream()
                .map(group -> group.get(0))  // 对应 C# 的 g.First()
                .collect(Collectors.toList());

//
//
//        // 修改：更宽松的去重策略，接近C#的行为
//        if (population.size() > _populationSize) {
//            Map<String, ScheduleChromosome> uniqueMap = new LinkedHashMap<>();
//            for (ScheduleChromosome chrom : population) {
//                // 使用更宽松的键：只基于设备分配和批次，忽略时间差异
//                String relaxedKey = generateRelaxedKey(chrom);
//                uniqueMap.putIfAbsent(relaxedKey, chrom);
//            }
//
//            // 如果去重后仍然过多，再使用严格键
//            if (uniqueMap.size() < _populationSize * 0.8) {
//                uniqueMap.clear();
//                for (ScheduleChromosome chrom : population) {
//                    uniqueMap.putIfAbsent(chrom.getGenesStr(), chrom);
//                }
//            }
//
//            population = new ArrayList<>(uniqueMap.values());
//            System.out.println("去重后种群大小: " + population.size());
//        }

        // 调试输出染色体多样性
        System.out.println("染色体多样性分析:");
        Map<String, Integer> keyCounts = new HashMap<>();
        for (ScheduleChromosome chrom : population) {
            String key = chrom.getGenesStr();
            keyCounts.put(key, keyCounts.getOrDefault(key, 0) + 1);
        }
        System.out.println("唯一染色体数量: " + keyCounts.size());
        System.out.println("染色体分布: " + keyCounts);

        // 并行计算适应度
        population.parallelStream().forEach(this::CalculateFitness);

        // 打印摘要
        population.forEach(this::WriteScheduleSummary);

        return population;
    }

    // 新增：生成宽松的键（只关注设备分配模式）
    private String generateRelaxedKey(ScheduleChromosome chrom) {
        return chrom.getGenes().stream()
                .sorted(Comparator.comparing(Gene::getOrderId)
                        .thenComparing(Gene::getOperationId))
                .map(g -> String.format("O%d-Op%d-M%d-B%d",
                        g.getOrderId(), g.getOperationId(), g.getMachineId(), g.getBatchSize()))
                .collect(Collectors.joining("|"));
    }

    private List<ScheduleChromosome> removeTrueDuplicates(List<ScheduleChromosome> population) {
        Map<String, ScheduleChromosome> uniqueMap = new LinkedHashMap<>();
        for (ScheduleChromosome chrom : population) {
            // 使用更宽松的键：包含批次大小、开始时间等关键信息
            String key = generateChromosomeKey(chrom);
            uniqueMap.putIfAbsent(key, chrom);
        }
        return new ArrayList<>(uniqueMap.values());
    }

    private String generateChromosomeKey(ScheduleChromosome chrom) {
        // 与C#一致的键生成逻辑：包含订单、工序、设备、批次、时间等关键信息
        return chrom.getGenes().stream()
                .sorted(Comparator.comparing(Gene::getOrderId)
                        .thenComparing(Gene::getOperationId)
                        .thenComparing(Gene::getStartTime))
                .map(g -> String.format("%d-%d-%d-%d-%d-%d",
                        g.getOrderId(), g.getOperationId(), g.getMachineId(),
                        g.getBatchSize(), g.getStartTime(), g.getEndTime()))
                .collect(Collectors.joining("|"));
    }


    // ========================== CalculateFitness（参数与C#一致） ==========================
    private void CalculateFitness(ScheduleChromosome chromosome) {
        // 1. 最大完工时间
        double makespan = chromosome.getGenes().stream()
                .mapToInt(Gene::getEndTime)
                .max()
                .orElse(0);

        // 2. 总延迟时间
        double tardiness = 0.0;
        Map<Integer, List<Gene>> orderGroups = chromosome.getGenes().stream()
                .collect(Collectors.groupingBy(Gene::getOrderId));

        for (Map.Entry<Integer, List<Gene>> group : orderGroups.entrySet()) {
            int orderCompletion = group.getValue().stream()
                    .mapToInt(Gene::getEndTime)
                    .max()
                    .orElse(0);
            Order order = _orders.stream()
                    .filter(o -> o.getId() == group.getKey())
                    .findFirst()
                    .orElse(null);

            if (order != null) {
                LocalDateTime completionTime = chromosome.getBaseTime().plusMinutes(orderCompletion);

                // 修复：正确处理OffsetDateTime到LocalDateTime的转换
                LocalDateTime dueDateTime = order.getDueDate().toLocalDateTime();

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

        // 3. 总换型时间
        double totalSetupTime = CalculateTotalSetupTime(chromosome);

        // 4. 总流程时间
        double totalFlowTime = CalculateTotalFlowTime(chromosome);

        // 5. 机器负载均衡
        double machineLoadBalance = CalculateMachineLoadBalance(chromosome);

        // 存储目标值（键与C#一致）
        double finalTardiness = tardiness;
        HashMap<Integer, Double> objMap = new HashMap<>();
        objMap.put(0, makespan);
        objMap.put(1, finalTardiness);
        objMap.put(2, totalSetupTime);
        objMap.put(3, totalFlowTime);
        objMap.put(4, machineLoadBalance);
        chromosome.setObjectiveValues(objMap);

        // 计算适应度
        chromosome.setFitness(
                0.4 * (1.0 / (1 + makespan)) +
                        0.3 * (1.0 / (1 + tardiness)) +
                        0.1 * (1.0 / (1 + totalSetupTime)) +
                        0.1 * (1.0 / (1 + totalFlowTime)) +
                        0.1 * machineLoadBalance
        );
    }


    // ========================== CalculateTotalFlowTime（参数与C#一致） ==========================
    private double CalculateTotalFlowTime(ScheduleChromosome chromosome) {
        double totalFlowTime = 0.0;
        Map<Integer, List<Gene>> orderGroups = chromosome.getGenes().stream()
                .collect(Collectors.groupingBy(Gene::getOrderId));

        for (Map.Entry<Integer, List<Gene>> group : orderGroups.entrySet()) {
            int minStartTime = group.getValue().stream().mapToInt(Gene::getStartTime).min().orElse(0);
            int maxEndTime = group.getValue().stream().mapToInt(Gene::getEndTime).max().orElse(0);

            LocalDateTime start = chromosome.getBaseTime().plusMinutes(minStartTime);
            LocalDateTime end = chromosome.getBaseTime().plusMinutes(maxEndTime);

            // 修复：计算流程时间（小时）
            long hours = ChronoUnit.HOURS.between(start, end);
            long minutes = ChronoUnit.MINUTES.between(start, end) % 60;
            totalFlowTime += hours + (double) minutes / 60;
        }

        return totalFlowTime;
    }


    // ========================== CalculateTotalSetupTime（参数与C#一致） ==========================
    private double CalculateTotalSetupTime(ScheduleChromosome chromosome) {
        double totalSetupTime = 0.0;
        Map<Integer, List<Gene>> machineGroups = chromosome.getGenes().stream()
                .collect(Collectors.groupingBy(Gene::getMachineId));

        for (Map.Entry<Integer, List<Gene>> machineGroup : machineGroups.entrySet()) {
            List<Gene> sortedGenes = machineGroup.getValue().stream()
                    .sorted(Comparator.comparingInt(Gene::getStartTime))
                    .collect(Collectors.toList());

            Integer lastProductId = null;
            for (Gene gene : sortedGenes) {
                if (lastProductId != null && lastProductId != gene.getProductId()) {
                    // 查找对应工序和设备选项
                    Product product = _products.stream()
                            .filter(p -> p.getId() == gene.getProductId())
                            .findFirst()
                            .orElse(null);
                    if (product == null) continue;

                    Operation operation = product.getOperations().stream()
                            .filter(o -> o.getId() == gene.getOperationId())
                            .findFirst()
                            .orElse(null);
                    if (operation == null) continue;

                    MachineOption machineOption = operation.getMachineOptions().stream()
                            .filter(m -> m.getMachineId() == gene.getMachineId())
                            .findFirst()
                            .orElse(null);
                    if (machineOption != null) {
                        totalSetupTime += machineOption.getSetupTime();
                    }
                }
                lastProductId = gene.getProductId();
            }
        }

        return totalSetupTime;
    }


    // ========================== CalculateMachineLoadBalance（参数与C#一致） ==========================
    private double CalculateMachineLoadBalance(ScheduleChromosome chromosome) {
        Map<Integer, Double> machineUtilization = new HashMap<>();
        int maxEndTime = chromosome.getGenes().stream()
                .mapToInt(Gene::getEndTime)
                .max()
                .orElse(0);

        if (maxEndTime == 0) return 0.0;

        // 计算设备忙碌时间
        for (Machine machine : _machines) {
            double busyTime = chromosome.getGenes().stream()
                    .filter(g -> g.getMachineId() == machine.getId())
                    .mapToInt(g -> g.getEndTime() - g.getStartTime())
                    .sum();
            machineUtilization.put(machine.getId(), busyTime / maxEndTime);
        }

        // 计算方差
        double avgUtilization = machineUtilization.values().stream().mapToDouble(Double::doubleValue).average().orElse(0.0);
        double variance = machineUtilization.values().stream()
                .mapToDouble(u -> Math.pow(u - avgUtilization, 2))
                .average()
                .orElse(0.0);

        // 负载均衡得分
        return 1.0 / (1 + variance);
    }


    // ========================== RemoveMachineAvailable（参数与C#一致） ==========================
    private void RemoveMachineAvailable(Machine machine, GeneDetail geneDetails) {
        List<TimeSegment> timeSegments = new ArrayList<>();

        // 查找对应时间段
        int index = machine.getAvailability().stream()
                .filter(t -> t.getKey().equals(geneDetails.getKey()))
                .findFirst()
                .map(machine.getAvailability()::indexOf)
                .orElse(-1);

        if (index > -1) {
            TimeSegment targetSegment = machine.getAvailability().get(index);
            LocalDateTime geneEndTime = baseTime.plusMinutes(geneDetails.getEndTime());

            if (targetSegment.getEnd().isAfter(geneEndTime)) {
                // 拆分时间段
                TimeSegment usedSegment = new TimeSegment();
                usedSegment.setStart(baseTime.plusMinutes(geneDetails.getStartTime()));
                usedSegment.setEnd(geneEndTime);
                usedSegment.setHoliday(false);
                usedSegment.setKey(UUID.randomUUID().toString());
                usedSegment.setType(SegmentType.REGULAR);
                usedSegment.setUsed(true);
                timeSegments.add(usedSegment);

                // 更新基因详情Key
                geneDetails.setKey(usedSegment.getKey());

                // 更新原时间段开始时间
                targetSegment.setStart(geneEndTime);
            } else {
                targetSegment.setUsed(true);
            }
        }

        // 添加新段并排序
        if (!timeSegments.isEmpty()) {
            machine.getAvailability().addAll(timeSegments);
        }
        machine.getAvailability().sort(Comparator.comparing(TimeSegment::getStart));
    }


    // ========================== AddMachineAvailable（参数与C#一致） ==========================
    private void AddMachineAvailable(Machine machine, List<GeneDetail> geneDetails) {
        if (geneDetails == null || geneDetails.isEmpty()) return;

        // 标记时间段为未占用
        for (GeneDetail detail : geneDetails) {
            machine.getAvailability().stream()
                    .filter(t -> t.getKey().equals(detail.getKey()))
                    .findFirst()
                    .ifPresent(t -> t.setUsed(false));
        }

        // 合并时间段
        machine.setAvailability(MergeSegments(machine.getAvailability()));
    }


    // ========================== MergeSegments（参数与C#一致） ==========================
    private List<TimeSegment> MergeSegments(List<TimeSegment> segments) {
        // 分离维护段、未占用段、已占用段
        List<TimeSegment> maintenanceSegments = segments.stream()
                .filter(t -> t.getType() == SegmentType.MAINTENANCE)
                .collect(Collectors.toList());

        List<TimeSegment> unusedRegularSegments = segments.stream()
                .filter(t -> t.getType() != SegmentType.MAINTENANCE && !t.isUsed())
                .collect(Collectors.toList());

        List<TimeSegment> usedRegularSegments = segments.stream()
                .filter(t -> t.getType() != SegmentType.MAINTENANCE && t.isUsed())
                .collect(Collectors.toList());

        // 排序未占用段
        unusedRegularSegments.sort(Comparator.comparing(TimeSegment::getStart));

        // 合并未占用段
        Deque<TimeSegment> mergedUnused = new ArrayDeque<>();
        for (TimeSegment seg : unusedRegularSegments) {
            if (!mergedUnused.isEmpty() && mergedUnused.peekLast().getEnd().isAfter(seg.getStart())) {
                TimeSegment last = mergedUnused.pollLast();
                last.setEnd(last.getEnd().isAfter(seg.getEnd()) ? last.getEnd() : seg.getEnd());
                mergedUnused.offerLast(last);
            } else {
                mergedUnused.offerLast(seg);
            }
        }

        // 重组结果
        List<TimeSegment> result = new ArrayList<>(mergedUnused);
        result.addAll(usedRegularSegments);
        result.addAll(maintenanceSegments);
        result.sort(Comparator.comparing(TimeSegment::getStart));

        return result;
    }


    // ========================== GetNextAvailableTime（参数与C#一致） ==========================
    private List<GeneDetail> GetNextAvailableTime(
            Machine machine, int proposedStartTime, int prevtime,
            int processingTime, List<Gene> existingTasks,
            boolean IsInterrupt, boolean istask
    ) {
        LocalDateTime startTime = baseTime.plusMinutes(proposedStartTime);
        String prevtimeStr = prevtime > -1 ? baseTime.plusMinutes(prevtime).toString() : "";

        // 查找最早可用班次
        return FindEarliestStart(machine, processingTime, startTime, prevtimeStr, existingTasks, istask);
    }


    // ========================== FindEarliestStart（参数与C#一致） ==========================
    private List<GeneDetail> FindEarliestStart(
            Machine machine, int processingTime, LocalDateTime currentTime,
            String prevtime, List<Gene> existingTasks, boolean checkprevtime
    ) {
        // 获取设备已有任务
        List<Gene> machineTasks = existingTasks.stream()
                .filter(t -> t.getMachineId() == machine.getId())
                .sorted(Comparator.comparingInt(Gene::getStartTime))
                .collect(Collectors.toList());

        List<GeneDetail> times = new ArrayList<>();

        // 获取当前或下一个班次
        TimeSegment slot = GetCurrentOrNextShift(machine, currentTime, prevtime, checkprevtime);
        if (slot == null) return times;

        // 计算候选时间
        LocalDateTime prevTimeDateTime = StringUtils.isEmpty(prevtime) ? null : LocalDateTime.parse(prevtime);
        LocalDateTime startCandidate = slot.getStart().isAfter(prevTimeDateTime != null ? prevTimeDateTime : currentTime)
                ? slot.getStart()
                : (prevTimeDateTime != null ? prevTimeDateTime : currentTime);
        LocalDateTime endCandidate = startCandidate.plusMinutes(processingTime);

        // 检查是否容纳
        if (endCandidate.isAfter(slot.getEnd())) {
            return CaldEarliestStart(machine, processingTime, currentTime, prevtime, machineTasks, checkprevtime);
        } else {
            // 创建时间详情
            GeneDetail time = new GeneDetail();
            time.setKey(slot.getKey());
            time.setStartTime((int) ChronoUnit.MINUTES.between(baseTime, startCandidate));
            time.setEndTime((int) ChronoUnit.MINUTES.between(baseTime, endCandidate));
            times.add(time);

            // 标记占用
            RemoveMachineAvailable(machine, time);
            return times;
        }
    }


    // ========================== CaldEarliestStart（参数与C#一致） ==========================
    private List<GeneDetail> CaldEarliestStart(
            Machine machine, int processingTime, LocalDateTime currentTime,
            String prevtime, List<Gene> machineTasks, boolean checkprevtime
    ) {
        int remainingTime = processingTime;
        LocalDateTime st = StringUtils.isEmpty(prevtime) ? currentTime : LocalDateTime.parse(prevtime);
        LocalDateTime prevEnd = LocalDateTime.of(2000, 1, 1, 0, 0, 0);
        List<GeneDetail> times = new ArrayList<>();
        List<GeneDetail> oldTimes = new ArrayList<>();

        while (remainingTime > 0) {
            TimeSegment shift = GetCurrentOrNextShift(machine, currentTime, prevtime, checkprevtime);
            if (shift == null) break;

            LocalDateTime shiftStart = shift.getStart();
            LocalDateTime shiftEnd = shift.getEnd();

            // 检查班次间冲突
            if (!prevEnd.isEqual(LocalDateTime.of(2000, 1, 1, 0, 0, 0))) {
                if (prevEnd.isBefore(currentTime)) {
                    // 检查班次间任务
                    LocalDateTime finalPrevEnd = prevEnd;
                    boolean hasTask = machineTasks.stream()
                            .anyMatch(t -> {
                                LocalDateTime taskStart = baseTime.plusMinutes(t.getStartTime());
                                return taskStart.isAfter(finalPrevEnd) && taskStart.isBefore(shiftStart);
                            });

                    if (hasTask) {
                        // 重置状态
                        currentTime = shiftStart;
                        st = shiftStart;
                        remainingTime = processingTime;
                        prevEnd = LocalDateTime.of(2000, 1, 1, 0, 0, 0);
                        oldTimes.addAll(deepCopyGeneDetailList(times));
                        times.clear();
                        continue;
                    }

                    // 检查班次间维修窗口
                    if (machine.getMaintenanceWindows() != null) {
                        LocalDateTime finalPrevEnd1 = prevEnd;
                        boolean hasMaintenance = machine.getMaintenanceWindows().stream()
                                .anyMatch(w -> w.getStartTime().isAfter(finalPrevEnd1) && w.getStartTime().isBefore(shiftStart));

                        if (hasMaintenance) {
                            currentTime = shiftStart;
                            st = shiftStart;
                            remainingTime = processingTime;
                            prevEnd = LocalDateTime.of(2000, 1, 1, 0, 0, 0);
                            times.clear();
                            continue;
                        }
                    }
                }
            }

            prevEnd = shiftEnd;
            // 计算有效时间
            LocalDateTime effectiveStart = st.isAfter(shiftStart) ? st : shiftStart;
            long availableMinutes = ChronoUnit.MINUTES.between(effectiveStart, shiftEnd);

            // 处理当前班次
            int processable = Math.min(remainingTime, (int) availableMinutes);
            remainingTime -= processable;
            currentTime = effectiveStart.plusMinutes(processable);

            // 添加时间详情
            GeneDetail time = new GeneDetail();
            time.setKey(shift.getKey());
            time.setStartTime((int) ChronoUnit.MINUTES.between(baseTime, effectiveStart));
            time.setEndTime((int) ChronoUnit.MINUTES.between(baseTime, currentTime));
            times.add(time);
            RemoveMachineAvailable(machine, time);
        }

        // 还原未使用的时间段
        AddMachineAvailable(machine, oldTimes);
        return times;
    }


    // ========================== GetCurrentOrNextShift（参数与C#一致） ==========================
    private TimeSegment GetCurrentOrNextShift(Machine machine, LocalDateTime time, String prevtime, boolean checkprevtime) {
        TimeSegment start = null;

        // 查找有效班次
        start = machine.getAvailability().stream()
                .filter(slot -> !slot.isUsed() && slot.getType() != SegmentType.MAINTENANCE)
                .filter(slot -> slot.getStart().isAfter(time) || slot.getEnd().isAfter(time))
                .findFirst()
                .orElse(null);

        if (start == null) {
            // 生成新时间段
            List<TimeSegment> timeSegments = _machineScheduler.generateTimeSegment(machine, time);
            machine.getAvailability().addAll(timeSegments);

            // 更新设备时间线
            Machine originalMachine = _machines.stream()
                    .filter(t -> t.getId() == machine.getId())
                    .findFirst()
                    .orElse(null);
            if (originalMachine != null) {
                MachineTimeline timeline = _machineScheduler.getOrCreateTimeline(originalMachine);
            }

            // 递归查找
            return GetCurrentOrNextShift(machine, time, prevtime, checkprevtime);
        }

        return start;
    }


    // ========================== PrintScheduleSummary（参数与C#一致） ==========================
    public void PrintScheduleSummary(ScheduleChromosome schedule) {
        System.out.println("\n=== Schedule Summary ===");

        // 按订单分组打印
        Map<Integer, List<Gene>> orderGroups = schedule.getGenes().stream()
                .collect(Collectors.groupingBy(Gene::getOrderId));

        for (Map.Entry<Integer, List<Gene>> group : orderGroups.entrySet()) {
            System.out.printf("\nOrder %d Schedule:%n", group.getKey());

            // 按工序排序
            List<Gene> sortedJobs = group.getValue().stream()
                    .sorted(Comparator.comparingInt(Gene::getOperationId))
                    .collect(Collectors.toList());

            for (Gene job : sortedJobs) {
                Product product = _products.stream()
                        .filter(p -> p.getId() == job.getProductId())
                        .findFirst()
                        .orElse(null);
                Operation operation = product != null ? product.getOperations().stream()
                        .filter(o -> o.getId() == job.getOperationId())
                        .findFirst()
                        .orElse(null) : null;

                if (product != null && operation != null) {
                    String print = String.format(
                            "[%s-%s] Order %d, Product %s, Machine %d, Operation %d, Batch %d, processingTime %d",
                            ConvertTime(job.getStartTime()),
                            ConvertTime(job.getEndTime()),
                            job.getOrderId(),
                            product.getName(),
                            job.getMachineId(),
                            operation.getSequence(),
                            job.getBatchSize(),
                            job.getProcessingTime()
                    );
                    System.out.println(print);
                }
            }
        }
    }


    // ========================== WriteScheduleSummary（参数与C#一致） ==========================
    public void WriteScheduleSummary(ScheduleChromosome schedule) {
        // 写入日志
        FileHelper.writeLogFile(String.format("\n=== Schedule Summary === %f", schedule.getFitness()));
        FileHelper.writeLogFile(String.format("Makespan: %f minutes", schedule.getObjectiveValues().get(0)));
        FileHelper.writeLogFile(String.format("Total Tardiness: %f hours", schedule.getObjectiveValues().get(1)));
        FileHelper.writeLogFile(String.format("Setup Time: %f minutes", schedule.getObjectiveValues().get(2)));
        FileHelper.writeLogFile(String.format("Flow Time: %f minutes", schedule.getObjectiveValues().get(3)));
        FileHelper.writeLogFile(String.format("Machine Load Balance: %.2f%%", schedule.getObjectiveValues().get(4) * 100));
        FileHelper.writeLogFile("-------------------------");

        // 按订单分组写入
        Map<Integer, List<Gene>> orderGroups = schedule.getGenes().stream()
                .collect(Collectors.groupingBy(Gene::getOrderId));

        for (Map.Entry<Integer, List<Gene>> group : orderGroups.entrySet()) {
            List<Gene> sortedJobs = group.getValue().stream()
                    .sorted(Comparator.comparingInt(Gene::getOperationId))
                    .collect(Collectors.toList());

            for (Gene job : sortedJobs) {
                Product product = _products.stream()
                        .filter(p -> p.getId() == job.getProductId())
                        .findFirst()
                        .orElse(null);
                Operation operation = product != null ? product.getOperations().stream()
                        .filter(o -> o.getId() == job.getOperationId())
                        .findFirst()
                        .orElse(null) : null;

                if (product != null && operation != null) {
                    StringBuilder sb = new StringBuilder();
                    sb.append(String.format(
                            "[%d-%d]:[%s-%s] Order %d, Product %s, Machine %d, Operation %d, Batch %d, processingTime %d",
                            job.getStartTime(),
                            job.getEndTime(),
                            ConvertTime(job.getStartTime()),
                            ConvertTime(job.getEndTime()),
                            job.getOrderId(),
                            product.getName(),
                            job.getMachineId(),
                            operation.getSequence(),
                            job.getBatchSize(),
                            job.getProcessingTime()
                    ));

                    // 追加基因详情
                    for (GeneDetail d : job.getGeneDetails()) {
                        sb.append(String.format(
                                "\n\t\t\t\t\t\t\t\t\t\t [%d-%d]:[%s-%s] %d",
                                d.getStartTime(),
                                d.getEndTime(),
                                ConvertTime(d.getStartTime()),
                                ConvertTime(d.getEndTime()),
                                d.getEndTime() - d.getStartTime()
                        ));
                    }

                    FileHelper.writeLogFile(sb.toString());
                }
            }
            FileHelper.writeLogFile("");
        }
    }


    // ========================== ConvertTime（参数与C#一致） ==========================
    private String ConvertTime(int minute) {
        return baseTime.plusMinutes(minute).format(java.time.format.DateTimeFormatter.ofPattern("MM-dd HH:mm"));
    }


    // ========================== 深拷贝工具方法（替换C# Mapster，方法名前缀统一为deepCopy） ==========================
    private List<Product> deepCopyProductList(List<Product> source) {
        return source == null ? new ArrayList<>() : source.stream().map(this::deepCopyProduct).collect(Collectors.toList());
    }

    private Product deepCopyProduct(Product source) {
        if (source == null) return null;
        Product copy = new Product();
        copy.setId(source.getId());
        copy.setName(source.getName());
        copy.setOperations(deepCopyOperationList(source.getOperations()));
        return copy;
    }

    private List<Operation> deepCopyOperationList(List<Operation> source) {
        return source == null ? new ArrayList<>() : source.stream().map(this::deepCopyOperation).collect(Collectors.toList());
    }

    private Operation deepCopyOperation(Operation source) {
        if (source == null) return null;
        Operation copy = new Operation();
        copy.setId(source.getId());
        copy.setProductId(source.getProductId());
        copy.setSequence(source.getSequence());
        copy.setInterrupt(source.isInterrupt());
        copy.setMachineOptions(deepCopyMachineOptionList(source.getMachineOptions()));
        return copy;
    }

    private List<MachineOption> deepCopyMachineOptionList(List<MachineOption> source) {
        return source == null ? new ArrayList<>() : source.stream().map(this::deepCopyMachineOption).collect(Collectors.toList());
    }

    private MachineOption deepCopyMachineOption(MachineOption source) {
        if (source == null) return null;
        MachineOption copy = new MachineOption();
        copy.setMachineId(source.getMachineId());
        copy.setProcessingTime(source.getProcessingTime());
        copy.setSetupTime(source.getSetupTime());
        return copy;
    }

    private List<Machine> deepCopyMachineList(List<Machine> source) {
        return source == null ? new ArrayList<>() : source.stream().map(this::deepCopyMachine).collect(Collectors.toList());
    }

    private Machine deepCopyMachine(Machine source) {
        if (source == null) return null;
        Machine copy = new Machine();
        copy.setId(source.getId());
        copy.setName(source.getName());
        copy.setEarliestTime(source.getEarliestTime());
        copy.setTotalTaskTime(source.getTotalTaskTime());
        copy.setShifts(deepCopyShiftList(source.getShifts()));
        copy.setMaintenanceWindows(deepCopyMaintenanceWindowList(source.getMaintenanceWindows()));
        copy.setAvailability(deepCopyTimeSegmentList(source.getAvailability()));
        copy.setShiftsChanged(source.getShiftsChanged());
        copy.setMaintenanceWindowsChanged(source.getMaintenanceWindowsChanged());
        return copy;
    }

    private List<Shift> deepCopyShiftList(List<Shift> source) {
        return source == null ? new ArrayList<>() : source.stream().map(this::deepCopyShift).collect(Collectors.toList());
    }

    private Shift deepCopyShift(Shift source) {
        if (source == null) return null;
        Shift copy = new Shift();
        copy.setStartTime(source.getStartTime());
        copy.setEndTime(source.getEndTime());
        copy.setDays(source.getDays() != null ? new HashSet<>(source.getDays()) : null);
        copy.setShiftDate(source.getShiftDate());
        copy.setTemporaryShift(source.isTemporaryShift());
        copy.setPriority(source.getPriority());
        return copy;
    }

    private List<MaintenanceWindow> deepCopyMaintenanceWindowList(List<MaintenanceWindow> source) {
        return source == null ? new ArrayList<>() : source.stream().map(this::deepCopyMaintenanceWindow).collect(Collectors.toList());
    }

    private MaintenanceWindow deepCopyMaintenanceWindow(MaintenanceWindow source) {
        if (source == null) return null;
        MaintenanceWindow copy = new MaintenanceWindow();
        copy.setStartTime(source.getStartTime());
        copy.setEndTime(source.getEndTime());
        copy.setReason(source.getReason());
        return copy;
    }

    private List<TimeSegment> deepCopyTimeSegmentList(List<TimeSegment> source) {
        return source == null ? new ArrayList<>() : source.stream().map(this::deepCopyTimeSegment).collect(Collectors.toList());
    }

    private TimeSegment deepCopyTimeSegment(TimeSegment source) {
        if (source == null) return null;
        TimeSegment copy = new TimeSegment();
        copy.setKey(source.getKey());
        copy.setStart(source.getStart());
        copy.setEnd(source.getEnd());
        copy.setEarliestTime(source.getEarliestTime());
        copy.setTotalTaskTime(source.getTotalTaskTime());
        copy.setType(source.getType());
        copy.setHoliday(source.isHoliday());
        copy.setUsed(source.isUsed());
        return copy;
    }

    private List<Order> deepCopyOrderList(List<Order> source) {
        return source == null ? new ArrayList<>() : source.stream().map(this::deepCopyOrder).collect(Collectors.toList());
    }

    private Order deepCopyOrder(Order source) {
        if (source == null) return null;
        Order copy = new Order();
        copy.setId(source.getId());
        copy.setProductId(source.getProductId());
        copy.setQuantity(source.getQuantity());
        copy.setDueDate(source.getDueDate());
        copy.setOrderCompletion(source.getOrderCompletion());
        copy.setTardiness(source.getTardiness());
        copy.setPriority(source.getPriority());
        copy.setCanSplit(source.isCanSplit());
        copy.setCanInterrupt(source.isCanInterrupt());
        return copy;
    }

    private List<Gene> deepCopyGeneList(List<Gene> source) {
        return source == null ? new ArrayList<>() : source.stream().map(this::deepCopyGene).collect(Collectors.toList());
    }

    private Gene deepCopyGene(Gene source) {
        if (source == null) return null;
        Gene copy = new Gene();
        copy.setOrderId(source.getOrderId());
        copy.setProductId(source.getProductId());
        copy.setOperationId(source.getOperationId());
        copy.setMachineId(source.getMachineId());
        copy.setBatchSize(source.getBatchSize());
        copy.setStartTime(source.getStartTime());
        copy.setEndTime(source.getEndTime());
        copy.setProcessingTime(source.getProcessingTime());
        copy.setGeneDetails(deepCopyGeneDetailList(source.getGeneDetails()));
        return copy;
    }

    private List<GeneDetail> deepCopyGeneDetailList(List<GeneDetail> source) {
        return source == null ? new ArrayList<>() : source.stream().map(this::deepCopyGeneDetail).collect(Collectors.toList());
    }

    private GeneDetail deepCopyGeneDetail(GeneDetail source) {
        if (source == null) return null;
        GeneDetail copy = new GeneDetail();
        copy.setKey(source.getKey());
        copy.setStartTime(source.getStartTime());
        copy.setEndTime(source.getEndTime());
        return copy;
    }

    private ScheduleChromosome deepCopyScheduleChromosome(ScheduleChromosome source) {
        if (source == null) return null;
        ScheduleChromosome copy = new ScheduleChromosome(source.getBaseTime());
        copy.setGenes(deepCopyGeneList(source.getGenes()));
        copy.setOrders(deepCopyOrderList(source.getOrders()));
        copy.setMachines(deepCopyMachineList(source.getMachines()));
        copy.setObjectiveValues(new HashMap<>(source.getObjectiveValues()));
        copy.setFitness(source.getFitness());
        copy.setTardiness(source.getTardiness());
        return copy;
    }


    // ========================== 辅助类：StringUtils（对应C#字符串工具） ==========================
    private static class StringUtils {
        public static boolean isEmpty(String str) {
            return str == null || str.trim().isEmpty();
        }
    }
}