package com.aps.service.plan;

import com.aps.common.util.ProductionDeepCopyUtil;
import com.aps.common.util.redis.RedisUtils;
import com.aps.entity.Algorithm.*;
import com.aps.entity.ApsTimeConfig;
import com.aps.entity.Dispatch;
import com.aps.entity.MesShiftWorkSched;
import com.aps.entity.PlanResource;
import com.aps.entity.Schedule.SceneChromsome;
import com.aps.entity.basic.*;

import com.aps.service.ApsTimeConfigService;
import com.aps.service.DispatchService;
import com.aps.service.MesShiftWorkSchedService;
import com.aps.service.PlanResourceService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

/**
 * 锁定期工单处理服务
 * 负责处理锁定期工单的加载、复制和添加到排产结果中
 */
@Slf4j
@Service
public class LockedOrderProcessorService {

    @Autowired
    private ApsTimeConfigService apsTimeConfigService;

    @Autowired
    private DispatchService dispatchService;

    @Autowired
    private SceneService sceneService;
    @Autowired
    private PlanResourceService planResourceService;

    @Autowired
    private MesShiftWorkSchedService mesShiftWorkSchedService;

    @Autowired
    private RedisUtils redisUtils;

    /**
     * 添加锁定期工单到调度结果中
     * 从上一次排产结果中获取冻结期内的工单，保持时间、数量、设备、Entry等信息不变
     * 
     * @param chromosome 染色体对象
     */
    public void addLockedOrdersToResult(Chromosome chromosome) {
        try {
            // 1. 获取锁定期配置
            LockPeriodConfig config = getLockPeriodConfig();
            if (config == null) {
                return;
            }

            log.debug("锁定期范围: {} 到 {} (冻结期: {}秒)", config.lockStartTime, config.lockEndTime, config.freezeSeconds);

            // 2. 从已下发场景获取锁定期工单
            LockedOrdersData lockedData = loadLockedOrdersFromScenes(config, chromosome.getBaseTime(), chromosome.getScenarioID());

//            // 3. 如果无法从已下发场景获取，则从Dispatch表创建
//            if (lockedData.results.isEmpty()) {
//                lockedData = createLockedOrdersFromDispatch(config, chromosome.getBaseTime());
//            }

            // 4. 添加锁定期工单到chromosome
            addLockedOrdersToChromosome(chromosome, lockedData, config);

        } catch (Exception e) {
            log.error("添加锁定期工单时发生错误: {}", e.getMessage(), e);
        }
    }

    /**
     * 获取锁定期配置
     */
    private LockPeriodConfig getLockPeriodConfig() {
        ApsTimeConfig timeConfig = apsTimeConfigService.getOne(new LambdaQueryWrapper<>());
        if (timeConfig == null || timeConfig.getBaseTime() == null) {
            log.warn("未找到ApsTimeConfig配置或baseTime为空，无法添加锁定期工单");
            return null;
        }

        LocalDateTime baseTime = timeConfig.getBaseTime();
        long freezeSeconds = timeConfig.getFreezeDate() != null ? timeConfig.getFreezeDate().longValue() : 0;

        if (freezeSeconds <= 0) {
            log.debug("冻结期秒数为{}，跳过添加锁定期工单", freezeSeconds);
            return null;
        }

        LockPeriodConfig config = new LockPeriodConfig();
        config.baseTime = baseTime;
        config.freezeSeconds = freezeSeconds;
        config.lockStartTime = baseTime;
        config.lockEndTime = baseTime.plusSeconds(freezeSeconds);

        return config;
    }
    /**
     * 从已下发场景加载锁定期工单
     */
    private LockedOrdersData loadLockedOrdersFromScenes(LockPeriodConfig config, LocalDateTime newBaseTime, String newSceneId) {
        LockedOrdersData data = new LockedOrdersData();

        try {
            // 查询锁定期内的Dispatch记录
            List<Dispatch> frozenDispatches = queryFrozenDispatches(config);
            if (frozenDispatches.isEmpty()) {
                log.debug("冻结期内没有工单需要添加");
                return data;
            }

            log.debug("查询到冻结期内的工序数: {}", frozenDispatches.size());

            // 获取所有不同的sceneId
            Set<String> dispatchSceneIds = frozenDispatches.stream()
                    .map(Dispatch::getSceneId)
                    .filter(id -> id != null && !id.isEmpty())
                    .collect(Collectors.toSet());

            if (dispatchSceneIds.isEmpty()) {
                log.warn("Dispatch表中的工单没有sceneId信息");
                return data;
            }

            log.debug("锁定期工单来自 {} 个已下发场景: {}", dispatchSceneIds.size(), dispatchSceneIds);

            // 遍历每个场景，加载锁定期工单
            for (String sceneId : dispatchSceneIds) {
                processSceneForLockedOrders(sceneId, frozenDispatches, config, newBaseTime, data, newSceneId);
            }

            log.debug("从 {} 个已下发场景排产结果中获取到 {} 个锁定期工单", dispatchSceneIds.size(), data.results.size());

        } catch (Exception ex) {
            log.error("从已下发场景排产结果获取锁定期工单失败: {}", ex.getMessage(), ex);
        }

        return data;
    }

    /**
     * 处理单个场景的锁定期工单
     */
    private void processSceneForLockedOrders(String sceneId, List<Dispatch> allDispatches, 
                                             LockPeriodConfig config, LocalDateTime newBaseTime, 
                                             LockedOrdersData data, String newSceneId) {
        try {
            log.debug("处理场景: {}", sceneId);

            // 加载场景的排产结果
            Chromosome dispatchChromosome = loadSceneChromosome(sceneId);
            if (dispatchChromosome == null || dispatchChromosome.getResult() == null) {
                return;
            }

            LocalDateTime dispatchBaseTime = dispatchChromosome.getBaseTime();
            if (dispatchBaseTime == null) {
                log.warn("场景 {} 的baseTime为空，无法计算时间偏移", sceneId);
                return;
            }

            log.debug("场景 {} - 已下发场景baseTime: {}, 新场景baseTime: {}", sceneId, dispatchBaseTime, newBaseTime);

            // 筛选属于当前场景的Dispatch记录
            List<Dispatch> currentSceneDispatches = allDispatches.stream()
                    .filter(d -> sceneId.equals(d.getSceneId()))
                    .collect(Collectors.toList());

            // 找出锁定期内的订单ID
            Set<String> lockedOrderIds = findLockedOrderIds(dispatchChromosome, currentSceneDispatches, 
                                                            config, dispatchBaseTime, sceneId);

            log.debug("场景 {} 中发现 {} 个订单在锁定期内有工序: {}", sceneId, lockedOrderIds.size(), lockedOrderIds);

            // 复制锁定期订单的所有工序
            copyLockedOrders(dispatchChromosome, currentSceneDispatches, lockedOrderIds, 
                           dispatchBaseTime, newBaseTime, sceneId, data, config);

            // 直接从已下发场景匹配Entry信息，避免ID冲突
            matchLockedEntriesFromDispatchScene(dispatchChromosome, data, sceneId, newSceneId);

        } catch (Exception ex) {
            log.error("处理场景 {} 的排产结果失败: {}", sceneId, ex.getMessage(), ex);
        }
    }

    /**
     * 直接从已下发场景匹配锁定期工单的Entry信息，避免ID冲突
     */
    private void matchLockedEntriesFromDispatchScene(Chromosome dispatchChromosome, LockedOrdersData data, String oldSceneId, String newSceneId) {
        if (dispatchChromosome.getAllOperations() == null) {
            return;
        }

        log.debug("场景 {} 中有 {} 个Entry，开始匹配锁定期工单的Entry信息", 
            oldSceneId, dispatchChromosome.getAllOperations().size());

        for (GAScheduleResult result : data.results) {
            log.debug("处理锁定期工单: ExecId={}, OperationId={}", result.getExecId(), result.getOperationId());

            // 直接从已下发场景的allOperations中查找Entry
            Entry entry = dispatchChromosome.getAllOperations().stream()
                    .filter(e -> e.getExecId().equals(result.getExecId()))
                    .findFirst()
                    .orElse(null);

            if (entry != null) {
                // 检查原始Entry的machineOptions
                log.debug("原始Entry {} 的machineOptions数量: {}", 
                    entry.getExecId(), 
                    entry.getMachineOptions() != null ? entry.getMachineOptions().size() : "null");
                
                if (entry.getMachineOptions() != null && !entry.getMachineOptions().isEmpty()) {
                    for (int i = 0; i < entry.getMachineOptions().size(); i++) {
                        MachineOption option = entry.getMachineOptions().get(i);
                        log.debug("  machineOption[{}]: machineId={}, equipCode={}, equipName={}", 
                            i, option.getMachineId(), option.getEquipCode(), option.getEquipName());
                    }
                }
                
                // 创建Entry副本，保持原有的machineOptions和设备信息
                Entry lockedEntry;
                try {
                    lockedEntry = ProductionDeepCopyUtil.deepCopy(entry);
                    log.debug("深拷贝后Entry {} 的machineOptions数量: {}, equipCode={}, equipName={}", 
                        lockedEntry.getExecId(), 
                        lockedEntry.getMachineOptions() != null ? lockedEntry.getMachineOptions().size() : "null",
                        lockedEntry.getEquipCode(), lockedEntry.getEquipName());
                } catch (Exception e) {
                    log.error("深拷贝Entry失败: {}", e.getMessage(), e);
                    lockedEntry = entry; // 失败时使用原始Entry
                }
                
                // 确保selectMachineID设置正确
                lockedEntry.setSelectMachineID(result.getMachineId());
                
                // 修复：不再过滤machineOptions，保持原有的所有设备选项
                // 原因：过滤machineOptions会导致在修改订单数量时，重新解码时无法正确处理
                // 解码器会根据所有可用的machineOptions进行调度，而不是被限制在单一设备
                // 这样可以避免因数量改变导致的时间冲突问题
                log.debug("锁定期Entry {} 保留所有machineOptions: 数量={}, equipCode={}, equipName={}", 
                    lockedEntry.getExecId(), 
                    lockedEntry.getMachineOptions() != null ? lockedEntry.getMachineOptions().size() : "null",
                    lockedEntry.getEquipCode(), lockedEntry.getEquipName());
                
                // 重要：更新sceneId为新场景ID，确保查询时能正确匹配
                if (newSceneId != null) {
                    String originalSceneId = lockedEntry.getSceneId();
                    lockedEntry.setSceneId(newSceneId);
                    log.debug("更新锁定期Entry的sceneId: {} -> {}", originalSceneId, newSceneId);
                }
                
                data.entries.put(result.getExecId(), lockedEntry);
                log.debug("从场景 {} 匹配到锁定期Entry: ExecId={}, 设备ID={}, equipCode={}, equipName={}, machineOptions数量={}", 
                    oldSceneId, result.getExecId(), result.getMachineId(), 
                    lockedEntry.getEquipCode(), lockedEntry.getEquipName(),
                    lockedEntry.getMachineOptions() != null ? lockedEntry.getMachineOptions().size() : "null");
            } else {
                log.warn("在场景 {} 中未找到工序 {} 对应的Entry", oldSceneId, result.getExecId());
            }
        }

        log.debug("场景 {} 成功匹配 {} 个Entry信息", oldSceneId, data.entries.size());
    }

    /**
     * 找出锁定期内的订单ID
     */
    private Set<String> findLockedOrderIds(Chromosome chromosome, List<Dispatch> dispatches, 
                                          LockPeriodConfig config, LocalDateTime baseTime, String sceneId) {
        Set<String> lockedOrderIds = new HashSet<>();
        
        log.debug("场景 {} 开始分析工序时间，锁定期范围: {} 到 {}", sceneId, config.lockStartTime, config.lockEndTime);

        for (GAScheduleResult result : chromosome.getResult()) {
            LocalDateTime startTime = baseTime.plusSeconds(result.getStartTime());

            log.debug("分析工序: ExecId={}, OrderId={}, 原始StartTime={}秒, 绝对开始时间={}", 
                result.getExecId(), result.getOrderId(), result.getStartTime(), startTime);

            // 检查工序是否在锁定期内
            if (!startTime.isBefore(config.lockStartTime) && !startTime.isAfter(config.lockEndTime)) {
                log.debug("工序在锁定期内: ExecId={}, OrderId={}, 开始时间={}", 
                    result.getExecId(), result.getOrderId(), startTime);

                // 通过订单号匹配Dispatch记录
                boolean hasValidDispatch = dispatches.stream()
                        .anyMatch(d -> d.getMesCode() != null && 
                                      d.getMesCode().equals(result.getOrderId()) &&
                                      d.getBeginTime() != null &&
                                      !d.getBeginTime().isBefore(config.lockStartTime) && 
                                      !d.getBeginTime().isAfter(config.lockEndTime));

                if (hasValidDispatch && result.getOrderId() != null) {
                    lockedOrderIds.add(result.getOrderId());
                    log.debug("订单 {} 被标记为锁定期订单（通过订单号匹配）", result.getOrderId());
                } else {
                    log.warn("工序 {} 在锁定期内但没有有效的Dispatch记录（订单号: {}）", 
                        result.getExecId(), result.getOrderId());
                }
            }
        }

        return lockedOrderIds;
    }

    /**
     * 复制锁定期订单的所有工序
     */
    private void copyLockedOrders(Chromosome chromosome, List<Dispatch> dispatches, 
                                 Set<String> lockedOrderIds, LocalDateTime oldBaseTime, 
                                 LocalDateTime newBaseTime, String sceneId, LockedOrdersData data, 
                                 LockPeriodConfig config) {
        for (GAScheduleResult result : chromosome.getResult()) {
            if (!lockedOrderIds.contains(result.getOrderId())) {
                continue;
            }

            // 检查是否有对应的Dispatch记录
            boolean hasDispatch = dispatches.stream()
                    .anyMatch(d -> d.getMesCode() != null && d.getMesCode().equals(result.getOrderId()));

            if (!hasDispatch) {
                log.warn("订单 {} 的工序 {} 没有对应的Dispatch记录", result.getOrderId(), result.getExecId());
                continue;
            }

            // 深拷贝工单并转换时间
            GAScheduleResult lockedResult = copyGAScheduleResult(result);
            lockedResult.setIsLocked(false); // 仍参与解码，通过固定开始时间保持原排程

            // 转换时间：从旧baseTime转换到新baseTime
            LocalDateTime prevStartTime = oldBaseTime.plusSeconds(result.getStartTime());
            LocalDateTime prevEndTime = oldBaseTime.plusSeconds(result.getEndTime());
            int newStartTime = (int) java.time.temporal.ChronoUnit.SECONDS.between(newBaseTime, prevStartTime);
            int newEndTime = (int) java.time.temporal.ChronoUnit.SECONDS.between(newBaseTime, prevEndTime);
            lockedResult.setStartTime(newStartTime);
            lockedResult.setEndTime(newEndTime);

            data.results.add(lockedResult);
            data.machineIds.add(result.getMachineId());

            boolean isInLockPeriod = !prevStartTime.isBefore(config.lockStartTime) && 
                                    !prevStartTime.isAfter(config.lockEndTime);
            log.debug("从场景 {} 获取订单 {} 的工序: ExecId={}, OrderCode={}, MachineId={}, 原始时间=[{} 到 {}], 新相对时间=[{} 到 {}]秒, 是否在锁定期内={}", 
                sceneId, result.getOrderId(), lockedResult.getExecId(), lockedResult.getOrderCode(), 
                lockedResult.getMachineId(), prevStartTime, prevEndTime, newStartTime, newEndTime, isInLockPeriod);
        }
    }
    /**
     * 匹配锁定期工单的Entry信息
     */
    private void matchLockedEntries(Chromosome chromosome, LockedOrdersData data, String sceneId) {
        if (chromosome.getAllOperations() == null) {
            return;
        }

        log.debug("场景 {} 中有 {} 个Entry，开始匹配锁定期工单的Entry信息", 
            sceneId, chromosome.getAllOperations().size());

        for (GAScheduleResult result : data.results) {
            log.debug("处理锁定期工单: ExecId={}, OperationId={}", result.getExecId(), result.getOperationId());

            Entry entry = null;
            if (result.getOperationId() > 0) {
                entry = chromosome.getAllOperations().stream()
                        .filter(e -> e.getId() == result.getOperationId())
                        .findFirst()
                        .orElse(null);
            }

            // 如果通过OperationId找不到，尝试通过ExecId匹配
            if (entry == null) {
                entry = chromosome.getAllOperations().stream()
                        .filter(e -> e.getExecId().equals(result.getExecId()))
                        .findFirst()
                        .orElse(null);

                if (entry != null) {
                    result.setOperationId(entry.getId());
                    log.debug("通过ExecId匹配到Entry并修正OperationId: ExecId={}, EntryId={}", 
                        result.getExecId(), entry.getId());
                }
            }

            if (entry != null) {
                data.entries.put(result.getExecId(), entry);
            } else {
                log.warn("未找到工序 {} 对应的Entry", result.getExecId());
            }
        }

        log.debug("场景 {} 成功匹配 {} 个Entry信息", sceneId, data.entries.size());
    }

    /**
     * 从Dispatch表创建锁定期工单
     */
    private LockedOrdersData createLockedOrdersFromDispatch(LockPeriodConfig config, LocalDateTime baseTime) {
        LockedOrdersData data = new LockedOrdersData();

        log.debug("从Dispatch表查询锁定期工单");
        List<Dispatch> frozenDispatches = queryFrozenDispatches(config);

        if (frozenDispatches.isEmpty()) {
            log.debug("冻结期内没有工单需要添加");
            return data;
        }

        log.debug("查询到冻结期内的工序数: {}", frozenDispatches.size());

        for (Dispatch dispatch : frozenDispatches) {
            GAScheduleResult result = createResultFromDispatch(dispatch, baseTime);
            data.results.add(result);
            data.machineIds.add(result.getMachineId());
        }

        return data;
    }
    /**
     * 从Dispatch记录创建GAScheduleResult
     */
    private GAScheduleResult createResultFromDispatch(Dispatch dispatch, LocalDateTime baseTime) {
        GAScheduleResult result = new GAScheduleResult();

        log.debug("处理Dispatch记录: id={}, executeId={}, mesCode={}, equipId={}, beginTime={}, endTime={}", 
            dispatch.getId(), dispatch.getExecuteId(), dispatch.getMesCode(), 
            dispatch.getEquipId(), dispatch.getBeginTime(), dispatch.getEndTime());

        // 设置基本信息
        result.setOperationId(dispatch.getExecuteId() != null ? dispatch.getExecuteId().intValue() : 0);
        result.setExecId(dispatch.getExecuteId() != null ? dispatch.getExecuteId().toString() : "");
        result.setOrderId(dispatch.getMesCode() != null ? dispatch.getMesCode() : "");
        result.setOrderCode(dispatch.getMesCode());
        result.setMachineId(dispatch.getEquipId() != null ? dispatch.getEquipId() : 0L);
        result.setQuantity(dispatch.getQuantity() != null ? dispatch.getQuantity() : 0.0);
        result.setProductId("");
        result.setProductName("");
        result.setProductCode("");

        log.debug("从Dispatch创建锁定期工单: executeId={}, OperationId={}, mesCode={}", 
            dispatch.getExecuteId(), result.getOperationId(), dispatch.getMesCode());

        // 计算相对时间
        if (dispatch.getBeginTime() != null && dispatch.getEndTime() != null) {
            int startTime = (int) java.time.temporal.ChronoUnit.SECONDS.between(baseTime, dispatch.getBeginTime());
            int endTime = (int) java.time.temporal.ChronoUnit.SECONDS.between(baseTime, dispatch.getEndTime());

            log.debug("锁定期工单时间计算: ExecId={}, Dispatch时间=[{} 到 {}], baseTime={}, 相对时间=[{} 到 {}]秒", 
                dispatch.getExecuteId(), dispatch.getBeginTime(), dispatch.getEndTime(), 
                baseTime, startTime, endTime);

            result.setStartTime(startTime);
            result.setEndTime(endTime);
            result.setProcessingTime((double) (endTime - startTime) / 60.0);
        }

        // 设置其他信息
        result.setIsLocked(true);
        result.setTeardownTime(0);
        result.setChangeOverTime(0);
        result.setPreTime(0);
        result.setSeq(dispatch.getTaskSeq() != null ? dispatch.getTaskSeq().intValue() : 0);
        result.setBomTime(0);
        result.setDesignatedStartTime(-1);
        result.setLockStartTime(0);
        // 关键修复：为dispatch工单设置forcedMachineId，确保重新解码时使用这个设备
        // 这样dispatch工单的设备就不会被改变
        result.setForcedMachineId(dispatch.getEquipId());

        // 创建GeneDetails
        List<ScheduleResultDetail> geneDetails = new ArrayList<>();
        ScheduleResultDetail detail = new ScheduleResultDetail();
        detail.setStartTime(result.getStartTime());
        detail.setEndTime(result.getEndTime());
        detail.setQuantity(dispatch.getQuantity() != null ? dispatch.getQuantity() : 0.0);
        geneDetails.add(detail);
        result.setGeneDetails(geneDetails);

        return result;
    }
    /**
     * 将锁定期工单添加到chromosome
     */
    private void addLockedOrdersToChromosome(Chromosome chromosome, LockedOrdersData data, LockPeriodConfig config) {
        // 1. 添加到result列表
        if (chromosome.getResult() == null) {
            chromosome.setResult(new CopyOnWriteArrayList<>());
        }

        int beforeSize = chromosome.getResult().size();
        chromosome.getResult().addAll(data.results);
        log.debug("成功添加 {} 个锁定期工单到调度结果中，result大小从{}变为{}", 
            data.results.size(), beforeSize, chromosome.getResult().size());

        // 1.5. 关键修复：将锁定期工单添加到ResultOld中，确保重新解码时能获取正确的设备ID
        if (chromosome.getResultOld() == null) {
            chromosome.setResultOld(new CopyOnWriteArrayList<>());
        }
        
        // 深拷贝锁定期工单的GAScheduleResult到ResultOld
        for (GAScheduleResult result : data.results) {
            try {
                GAScheduleResult resultCopy = ProductionDeepCopyUtil.deepCopy(result);
                chromosome.getResultOld().add(resultCopy);
                log.debug("添加锁定期工单到ResultOld: OperationId={}, MachineId={}, IsLocked={}", 
                    resultCopy.getOperationId(), resultCopy.getMachineId(), resultCopy.isIsLocked());
            } catch (Exception e) {
                log.error("深拷贝GAScheduleResult失败: {}", e.getMessage(), e);
                chromosome.getResultOld().add(result); // 失败时使用原始对象
            }
        }
        log.debug("成功添加 {} 个锁定期工单到ResultOld中", data.results.size());

        // 2. 复制锁定期订单的Order对象
        copyLockedOrderObjects(chromosome, data, config);

        // 3. 添加Entry到allOperations，并重新分配ID避免冲突
        if (!data.entries.isEmpty() && chromosome.getAllOperations() != null) {
            int beforeEntrySize = chromosome.getAllOperations().size();
            
            // 获取当前最大的Entry ID，避免ID冲突
            int maxExistingId = chromosome.getAllOperations().stream()
                    .mapToInt(Entry::getId)
                    .max()
                    .orElse(0);
            
            int nextAvailableId = maxExistingId + 1;
            Map<Integer, Integer> lockedEntryIdMapping = new HashMap<>();
            
            // 为锁定期Entry重新分配ID
            for (Entry lockedEntry : data.entries.values()) {
                int oldId = lockedEntry.getId();
                lockedEntryIdMapping.put(oldId, nextAvailableId);
                lockedEntry.setId(nextAvailableId);
                
                // 更新对应的GAScheduleResult的operationId（包括result和resultOld）
                int finalNextAvailableId = nextAvailableId;
                
                // 更新result中的operationId
                data.results.stream()
                        .filter(result -> result.getOperationId() == oldId)
                        .forEach(result -> result.setOperationId(finalNextAvailableId));
                
                // 关键修复：同时更新resultOld中的operationId
                if (chromosome.getResultOld() != null) {
                    chromosome.getResultOld().stream()
                            .filter(result -> result.getOperationId() == oldId)
                            .forEach(result -> {
                                result.setOperationId(finalNextAvailableId);
                                log.debug("更新ResultOld中的operationId: {} -> {}, ExecId={}", 
                                    oldId, finalNextAvailableId, result.getExecId());
                            });
                }
                
                log.debug("锁定期Entry ID重新分配: {} -> {}, ExecId={}", 
                    oldId, nextAvailableId, lockedEntry.getExecId());
                
                nextAvailableId++;
            }
            
            // 同步更新锁定期Entry内部依赖中的工序ID引用（仅修正本批次重分配的ID）
            for (Entry lockedEntry : data.entries.values()) {
                if (lockedEntry.getPrevEntryIds() != null) {
                    for (OperationDependency dep : lockedEntry.getPrevEntryIds()) {
                        if (dep == null) {
                            continue;
                        }
                        Integer newPrev = lockedEntryIdMapping.get(dep.getPrevOperationId());
                        if (newPrev != null) {
                            dep.setPrevOperationId(newPrev);
                        }
                        Integer newNext = lockedEntryIdMapping.get(dep.getNextOperationId());
                        if (newNext != null) {
                            dep.setNextOperationId(newNext);
                        }
                    }
                }

                if (lockedEntry.getNextEntryIds() != null) {
                    for (OperationDependency dep : lockedEntry.getNextEntryIds()) {
                        if (dep == null) {
                            continue;
                        }
                        Integer newPrev = lockedEntryIdMapping.get(dep.getPrevOperationId());
                        if (newPrev != null) {
                            dep.setPrevOperationId(newPrev);
                        }
                        Integer newNext = lockedEntryIdMapping.get(dep.getNextOperationId());
                        if (newNext != null) {
                            dep.setNextOperationId(newNext);
                        }
                    }
                }
            }

            // 同步更新锁定期Entry内部依赖中的工序ID引用（仅修正本批次重分配的ID）
            for (Entry lockedEntry : data.entries.values()) {
                if (lockedEntry.getPrevEntryIds() != null) {
                    for (OperationDependency dep : lockedEntry.getPrevEntryIds()) {
                        if (dep == null) {
                            continue;
                        }
                        Integer newPrev = lockedEntryIdMapping.get(dep.getPrevOperationId());
                        if (newPrev != null) {
                            dep.setPrevOperationId(newPrev);
                        }
                        Integer newNext = lockedEntryIdMapping.get(dep.getNextOperationId());
                        if (newNext != null) {
                            dep.setNextOperationId(newNext);
                        }
                    }
                }

                if (lockedEntry.getNextEntryIds() != null) {
                    for (OperationDependency dep : lockedEntry.getNextEntryIds()) {
                        if (dep == null) {
                            continue;
                        }
                        Integer newPrev = lockedEntryIdMapping.get(dep.getPrevOperationId());
                        if (newPrev != null) {
                            dep.setPrevOperationId(newPrev);
                        }
                        Integer newNext = lockedEntryIdMapping.get(dep.getNextOperationId());
                        if (newNext != null) {
                            dep.setNextOperationId(newNext);
                        }
                    }
                }
            }

            chromosome.getAllOperations().addAll(data.entries.values());
            log.debug("成功添加 {} 个锁定期Entry到allOperations中，大小从{}变为{}，ID范围: {}-{}", 
                data.entries.size(), beforeEntrySize, chromosome.getAllOperations().size(),
                maxExistingId + 1, nextAvailableId - 1);
        }

        // 4. 确保锁定期设备存在
        ensureLockedMachines(chromosome, data.machineIds, config);
        
        // 5. 将锁定期订单添加到operationSequencing中，确保它们会被解码处理
        if (!data.entries.isEmpty() && chromosome.getOperationSequencing() != null) {
            CopyOnWriteArrayList<Integer> currentSequencing = new CopyOnWriteArrayList<>(chromosome.getOperationSequencing());
            
            // 获取所有锁定期订单的ID
            Set<String> lockedOrderIds = data.entries.values().stream()
                    .map(Entry::getOrderId)
                    .collect(Collectors.toSet());
            
            // 为每个锁定期订单添加其所有工序到排产序列
            for (String orderId : lockedOrderIds) {
                // 找到该订单的所有工序，按sequence排序
                List<Entry> orderEntries = data.entries.values().stream()
                        .filter(entry -> orderId.equals(entry.getOrderId()))
                        .sorted(Comparator.comparing(Entry::getSequence))
                        .collect(Collectors.toList());
                
                // 将每个工序的groupId添加到operationSequencing
                for (Entry entry : orderEntries) {
                    currentSequencing.add(entry.getGroupId());
                    log.debug("添加锁定期工序到排产序列: OrderId={}, GroupId={}, Sequence={}", 
                        orderId, entry.getGroupId(), entry.getSequence());
                }
            }
            
            chromosome.setOperationSequencing(currentSequencing);
            log.debug("更新operationSequencing，从{}个工序增加到{}个工序", 
                chromosome.getOperationSequencing().size() - (currentSequencing.size() - chromosome.getOperationSequencing().size()), 
                currentSequencing.size());
        }
        
        // 6. 关键修复：将锁定期Entry添加到globalOpList中，确保重新解码时不会丢失
        if (!data.entries.isEmpty() && chromosome.getGlobalOpList() != null) {
            // 获取当前最大的globalOpId
            int maxGlobalOpId = chromosome.getGlobalOpList().stream()
                    .mapToInt(GlobalOperationInfo::getGlobalOpId)
                    .max()
                    .orElse(-1);
            
            int nextGlobalOpId = maxGlobalOpId + 1;
            
            // 为每个锁定期Entry创建GlobalOperationInfo并添加到globalOpList
            List<Entry> sortedEntries = data.entries.values().stream()
                    .sorted(Comparator.comparing(Entry::getGroupId)
                            .thenComparing(Entry::getSequence))
                    .collect(Collectors.toList());
            
            for (Entry lockedEntry : sortedEntries) {
                GlobalOperationInfo info = new GlobalOperationInfo();
                info.setGlobalOpId(nextGlobalOpId);
                info.setGroupId(lockedEntry.getGroupId());
                info.setSequence(lockedEntry.getSequence());
                info.setOp(lockedEntry);
                
                chromosome.getGlobalOpList().add(info);
                
                log.debug("添加锁定期Entry到globalOpList: GlobalOpId={}, EntryId={}, OrderCode={}, GroupId={}, Sequence={}, EquipCode={}", 
                    nextGlobalOpId, lockedEntry.getId(), lockedEntry.getOrderCode(), 
                    lockedEntry.getGroupId(), lockedEntry.getSequence(), lockedEntry.getEquipCode());
                
                nextGlobalOpId++;
            }
            
            log.debug("成功添加 {} 个锁定期Entry到globalOpList中，globalOpList大小变为{}", 
                sortedEntries.size(), chromosome.getGlobalOpList().size());
        }
        
        // 7. 关键修复：同步更新machineSelection，确保长度与globalOpList一致
        if (!data.entries.isEmpty() && chromosome.getMachineSelection() != null) {
            List<Integer> machineSelection = chromosome.getMachineSelection();
            
            // 为每个锁定期Entry添加机器选择索引
            // 锁定期工序的机器已经确定，所以机器选择索引设为1（表示使用machineOptions中的第一个，也是唯一的机器）
            // 注意：machineSelection的索引是从1开始的，不是从0开始
            List<Entry> sortedEntries = data.entries.values().stream()
                    .sorted(Comparator.comparing(Entry::getGroupId)
                            .thenComparing(Entry::getSequence))
                    .collect(Collectors.toList());
            
            for (Entry lockedEntry : sortedEntries) {
                // 锁定期工序的机器已经确定，machineSelection设为1（索引从1开始）
                machineSelection.add(1);
                
                log.debug("添加锁定期Entry的机器选择: EntryId={}, OrderCode={}, EquipCode={}, MachineSelectionIndex=1", 
                    lockedEntry.getId(), lockedEntry.getOrderCode(), lockedEntry.getEquipCode());
            }
            
            log.debug("成功添加 {} 个锁定期Entry的机器选择到machineSelection中，machineSelection大小变为{}", 
                sortedEntries.size(), machineSelection.size());
            
            // 验证：确保machineSelection长度与globalOpList长度一致
            if (chromosome.getGlobalOpList().size() != machineSelection.size()) {
                log.error("警告：machineSelection长度({})与globalOpList长度({})不一致！", 
                    machineSelection.size(), chromosome.getGlobalOpList().size());
            } else {
                log.debug("验证通过：machineSelection长度({})与globalOpList长度({})一致", 
                    machineSelection.size(), chromosome.getGlobalOpList().size());
            }
        }
    }

    /**
     * 复制锁定期订单的Order对象
     */
    private void copyLockedOrderObjects(Chromosome chromosome, LockedOrdersData data, LockPeriodConfig config) {
        if (data.results.isEmpty()) {
            return;
        }

        if (chromosome.getOrders() == null) {
            chromosome.setOrders(new CopyOnWriteArrayList<>());
        }

        int beforeOrderSize = chromosome.getOrders().size();

        // 收集锁定期订单ID
        Set<String> lockedOrderIds = data.results.stream()
                .map(GAScheduleResult::getOrderId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());

        log.debug("需要复制的锁定期订单ID: {}", lockedOrderIds);

        // 用于存储OrderId到新Order.id的映射
        Map<String, Integer> orderIdToNewGroupId = new HashMap<>();

        try {
            // 查询锁定期Dispatch记录
            List<Dispatch> frozenDispatches = queryFrozenDispatches(config);
            log.debug("查询到 {} 个锁定期Dispatch记录", frozenDispatches.size());

            Set<String> dispatchSceneIds = frozenDispatches.stream()
                    .map(Dispatch::getSceneId)
                    .filter(id -> id != null && !id.isEmpty())
                    .collect(Collectors.toSet());

            log.debug("锁定期Dispatch记录来自 {} 个场景: {}", dispatchSceneIds.size(), dispatchSceneIds);

            // 从每个场景复制订单，并收集Order ID映射
            for (String sceneId : dispatchSceneIds) {
                Map<String, Integer> sceneMapping = copyOrdersFromScene(chromosome, sceneId, lockedOrderIds);
                orderIdToNewGroupId.putAll(sceneMapping);
            }
            
            log.debug("Order ID映射: {}", orderIdToNewGroupId);
            
            // 更新Entry的groupId
            updateEntryGroupIds(data, orderIdToNewGroupId);
            
            // 更新GAScheduleResult的groupId
            updateResultGroupIds(data, orderIdToNewGroupId);
            
        } catch (Exception e) {
            log.error("复制锁定期订单失败: {}", e.getMessage(), e);
        }

        log.debug("成功复制锁定期订单到Orders列表，大小从{}变为{}", beforeOrderSize, chromosome.getOrders().size());
    }
    /**
     * 从场景复制订单，并返回OrderId到新Order.id的映射
     * @return Map<OrderId, 新Order.id>
     */
    private Map<String, Integer> copyOrdersFromScene(Chromosome chromosome, String sceneId, Set<String> lockedOrderIds) {
        Map<String, Integer> orderIdToNewGroupId = new HashMap<>();
        
        try {
            log.debug("开始从场景 {} 加载Chromosome", sceneId);
            Chromosome dispatchChromosome = sceneService.loadChromosomeFromFile(sceneId);

            if (dispatchChromosome == null) {
                log.warn("场景 {} 加载失败，Chromosome为null", sceneId);
                return orderIdToNewGroupId;
            }

            log.debug("场景 {} 加载成功，Orders数量: {}", sceneId, 
                dispatchChromosome.getOrders() != null ? dispatchChromosome.getOrders().size() : 0);

            if (dispatchChromosome.getOrders() == null) {
                log.warn("场景 {} 的Orders为null", sceneId);
                return orderIdToNewGroupId;
            }

            // 筛选锁定期订单
            List<Order> lockedOrders = dispatchChromosome.getOrders().stream()
                    .filter(order -> lockedOrderIds.contains(order.getOrderId()))
                    .collect(Collectors.toList());

            log.debug("场景 {} 中找到 {} 个匹配的锁定期订单", sceneId, lockedOrders.size());

            // 获取当前最大的Order ID
            int maxOrderId = chromosome.getOrders().stream()
                    .mapToInt(Order::getId)
                    .max()
                    .orElse(0);
            
            log.debug("当前最大Order ID: {}", maxOrderId);

            // 复制订单（避免重复）
            for (Order lockedOrder : lockedOrders) {
                boolean exists = chromosome.getOrders().stream()
                        .anyMatch(order -> lockedOrder.getOrderId().equals(order.getOrderId()));

                if (!exists) {
                    // 为dispatch工单分配新的Order ID
                    int oldOrderId = lockedOrder.getId();
                    int newOrderId = ++maxOrderId;
                    lockedOrder.setId(newOrderId);
                    
                    // 记录映射关系
                    orderIdToNewGroupId.put(lockedOrder.getOrderId(), newOrderId);
                    
                    log.debug("从场景 {} 复制锁定期订单: OrderId={}, OrderCode={}, 旧Order.id={}, 新Order.id={}", 
                        sceneId, lockedOrder.getOrderId(), lockedOrder.getOrderCode(), oldOrderId, newOrderId);
                    
                    chromosome.getOrders().add(lockedOrder);
                } else {
                    log.warn("订单 {} 已存在，跳过复制", lockedOrder.getOrderId());
                }
            }
        } catch (Exception ex) {
            log.error("从场景 {} 复制锁定期订单失败: {}", sceneId, ex.getMessage(), ex);
        }
        
        return orderIdToNewGroupId;
    }

    /**
     * 更新Entry的groupId
     */
    private void updateEntryGroupIds(LockedOrdersData data, Map<String, Integer> orderIdToNewGroupId) {
        if (orderIdToNewGroupId.isEmpty()) {
            return;
        }
        
        log.debug("开始更新Entry的groupId，映射数量: {}", orderIdToNewGroupId.size());
        
        for (Entry entry : data.entries.values()) {
            String orderId = entry.getOrderId();
            if (orderIdToNewGroupId.containsKey(orderId)) {
                int oldGroupId = entry.getGroupId();
                int newGroupId = orderIdToNewGroupId.get(orderId);
                entry.setGroupId(newGroupId);
                log.debug("更新Entry的groupId: ExecId={}, OrderId={}, 旧groupId={}, 新groupId={}", 
                    entry.getExecId(), orderId, oldGroupId, newGroupId);
            }
        }
        
        log.debug("Entry的groupId更新完成");
    }

    /**
     * 更新GAScheduleResult的groupId
     */
    private void updateResultGroupIds(LockedOrdersData data, Map<String, Integer> orderIdToNewGroupId) {
        if (orderIdToNewGroupId.isEmpty()) {
            return;
        }
        
        log.debug("开始更新GAScheduleResult的groupId，映射数量: {}", orderIdToNewGroupId.size());
        
        for (GAScheduleResult result : data.results) {
            String orderId = result.getOrderId();
            if (orderIdToNewGroupId.containsKey(orderId)) {
                int oldGroupId = result.getGroupId();
                int newGroupId = orderIdToNewGroupId.get(orderId);
                result.setGroupId(newGroupId);
                log.debug("更新GAScheduleResult的groupId: ExecId={}, OrderId={}, 旧groupId={}, 新groupId={}", 
                    result.getExecId(), orderId, oldGroupId, newGroupId);
            }
        }
        
        log.debug("GAScheduleResult的groupId更新完成");
    }

    /**
     * 确保锁定期设备存在于initMachines中
     */
    private void ensureLockedMachines(Chromosome chromosome, Set<Long> lockedMachineIds, LockPeriodConfig config) {
        if (chromosome.getInitMachines() == null || lockedMachineIds.isEmpty()) {
            return;
        }

        Set<Long> existingMachineIds = chromosome.getInitMachines().stream()
                .map(Machine::getId)
                .collect(Collectors.toSet());

        Set<Long> missingMachineIds = lockedMachineIds.stream()
                .filter(id -> id != null && id > 0 && !existingMachineIds.contains(id))
                .collect(Collectors.toSet());

        if (missingMachineIds.isEmpty()) {
            return;
        }

        log.debug("锁定期工单使用的设备不在本次排产中，需要从已下发场景获取设备信息: {}", missingMachineIds);

        try {
            List<Dispatch> frozenDispatches = queryFrozenDispatches(config);
            Set<String> dispatchSceneIds = frozenDispatches.stream()
                    .map(Dispatch::getSceneId)
                    .filter(id -> id != null && !id.isEmpty())
                    .collect(Collectors.toSet());

            // 从各个场景查找设备
            for (String sceneId : dispatchSceneIds) {
                if (missingMachineIds.isEmpty()) {
                    break;
                }
                loadMachinesFromScene(chromosome, sceneId, missingMachineIds);
            }

            // 如果还有设备没找到，创建默认设备
            if (!missingMachineIds.isEmpty()) {
                log.warn("在所有已下发场景中都没有找到锁定期设备，将创建默认设备信息: {}", missingMachineIds);
                createDefaultMachines(chromosome, missingMachineIds);
            }
        } catch (Exception ex) {
            log.error("从已下发场景排产结果获取设备信息失败: {}", ex.getMessage(), ex);
            createDefaultMachines(chromosome, missingMachineIds);
        }
    }
    /**
     * 从指定场景加载设备信息
     */
    private void loadMachinesFromScene(Chromosome chromosome, String sceneId, Set<Long> missingMachineIds) {
        try {
            log.debug("从场景 {} 获取设备信息", sceneId);

            Chromosome dispatchChromosome = loadSceneChromosome(sceneId);
            if (dispatchChromosome == null || dispatchChromosome.getInitMachines() == null) {
                return;
            }

            List<Machine> foundMachines = dispatchChromosome.getInitMachines().stream()
                    .filter(m -> missingMachineIds.contains(m.getId()))
                    .collect(Collectors.toList());

            if (!foundMachines.isEmpty()) {
                log.debug("从场景 {} 的排产结果中找到 {} 个锁定期设备", sceneId, foundMachines.size());
                chromosome.getInitMachines().addAll(foundMachines);

                Set<Long> foundIds = foundMachines.stream()
                        .map(Machine::getId)
                        .collect(Collectors.toSet());
                missingMachineIds.removeAll(foundIds);
            }
        } catch (Exception ex) {
            log.error("从场景 {} 获取设备信息失败: {}", sceneId, ex.getMessage(), ex);
        }
    }

    /**
     * 加载场景的Chromosome
     */
    private Chromosome loadSceneChromosome(String sceneId) {
        try {
            SceneChromsome sceneChromsome = (SceneChromsome) redisUtils.get("SceneId." + sceneId);
            if (sceneChromsome == null) {
                log.warn("未找到场景 {} 的版本信息", sceneId);
                return null;
            }

            int version = sceneChromsome.getVersion();
            File file = new File("result", "chromosome_result_" + sceneId + "_" + version + "_.json");

            if (!file.exists()) {
                log.warn("场景 {} 的排产结果文件不存在: {}", sceneId, file.getAbsolutePath());
                return null;
            }

            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.registerModule(new JavaTimeModule());
            objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
            objectMapper.configure(com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

            return objectMapper.readValue(file, Chromosome.class);
        } catch (Exception ex) {
            log.error("加载场景 {} 失败: {}", sceneId, ex.getMessage(), ex);
            return null;
        }
    }

    /**
     * 查询冻结期内的Dispatch记录
     */
    private List<Dispatch> queryFrozenDispatches(LockPeriodConfig config) {
        return dispatchService.lambdaQuery()
                .ge(Dispatch::getBeginTime, config.lockStartTime)
                .le(Dispatch::getBeginTime, config.lockEndTime)
                .eq(Dispatch::getIsDeleted, 0L)
                .orderBy(true, true, Dispatch::getMesCode, Dispatch::getTaskSeq)
                .list();
    }
    /**
     * 为锁定期工单创建默认设备信息
     * @param chromosome 染色体对象
     * @param machineIds 需要创建的设备ID集合
     */
    private void createDefaultMachines(Chromosome chromosome, Set<Long> machineIds) {
        try {
            // 查询这些设备的信息
            List<PlanResource> planResources = planResourceService.lambdaQuery()
                    .eq(PlanResource::getIsdeleted, 0)
                    .in(PlanResource::getId, machineIds.stream()
                            .map(Long::intValue)
                            .collect(Collectors.toList()))
                    .list();
            
            // 查询班次信息
            List<MesShiftWorkSched> allShiftWorkScheds = mesShiftWorkSchedService.lambdaQuery()
                    .eq(MesShiftWorkSched::getIsdeleted, 0)
                    .list();
            
            // 创建Machine对象并添加到initMachines
            for (Long machineId : machineIds) {
                Machine machine = new Machine();
                machine.setId(machineId);
                
                PlanResource planResource = planResources.stream()
                        .filter(pr -> pr.getId() == machineId.intValue())
                        .findFirst()
                        .orElse(null);
                
                if (planResource != null) {
                    machine.setCode(planResource.getReferenceCode());
                    machine.setName(planResource.getTitle());
                    machine.setDepartment(planResource.getDepartTitle());
                    
                    log.debug("为设备 {} 查询班次信息，workSchedId: {}", machineId, planResource.getWorkSchedId());
                    
                    // 查询设备的真实班次信息
                    List<MesShiftWorkSched> shiftWorkScheds = allShiftWorkScheds.stream()
                            .filter(t -> (long) t.getWeekWorkSchedId() == planResource.getWorkSchedId())
                            .collect(Collectors.toList());
                    
                    log.debug("设备 {} 找到 {} 个班次记录", machineId, shiftWorkScheds.size());
                    
                    if (!shiftWorkScheds.isEmpty()) {
                        // 使用真实的班次信息
                        List<Shift> shifts = mergeShiftData(shiftWorkScheds);
                        for (Shift shift : shifts) {
                            shift.setMachineId(machineId);
                            shift.setSpecial(false);
                            shift.setStartDate(LocalDateTime.of(2000, 1, 1, 0, 0, 0));
                            shift.setEndDate(LocalDateTime.of(2000, 1, 1, 0, 0, 0));
                        }
                        machine.setShifts(shifts);
                        log.debug("为设备 {} 设置真实班次信息，共 {} 个班次", machineId, shifts.size());
                    } else {
                        // 如果没有找到班次信息，使用默认24小时班次
                        machine.setShifts(createDefault24HourShift(machineId));
                        log.warn("设备 {} 没有找到班次信息，使用默认24小时班次", machineId);
                    }
                } else {
                    machine.setCode("LOCKED-" + machineId);
                    machine.setName("锁定期设备-" + machineId);
                    // 使用默认24小时班次
                    machine.setShifts(createDefault24HourShift(machineId));
                    log.warn("设备 {} 没有找到PlanResource信息，使用默认24小时班次", machineId);
                }
                
                chromosome.getInitMachines().add(machine);
            }
            
            log.debug("成功创建 {} 个默认锁定期设备", machineIds.size());
        } catch (Exception e) {
            log.error("创建默认设备信息失败: {}", e.getMessage(), e);
        }
    }
    
    /**
     * 创建默认的24小时班次
     * @param machineId 设备ID
     * @return 24小时班次列表
     */
    private List<Shift> createDefault24HourShift(Long machineId) {
        List<Shift> shifts = new ArrayList<>();
        Shift shift = new Shift();
        shift.setMachineId(machineId);
        shift.setStartTime(LocalTime.of(0, 0, 0));
        shift.setEndTime(LocalTime.of(23, 59, 59));
        HashSet<Integer> days = new HashSet<>();
        for (int i = 0; i <= 6; i++) {
            days.add(i);
        }
        shift.setDays(days);
        shift.setSpecial(false);
        shift.setStartDate(LocalDateTime.of(2000, 1, 1, 0, 0, 0));
        shift.setEndDate(LocalDateTime.of(2000, 1, 1, 0, 0, 0));
        shifts.add(shift);
        return shifts;
    }
    /**
     * 合并班次数据
     * @param shiftWorkScheds 班次工作计划列表
     * @return 合并后的班次列表
     */
    private List<Shift> mergeShiftData(List<MesShiftWorkSched> shiftWorkScheds) {
        // 这里需要根据实际的MesShiftWorkSched结构来实现班次合并逻辑
        // 暂时返回默认24小时班次，实际项目中需要根据具体需求实现
        List<Shift> shifts = new ArrayList<>();
        
        // 按班次分组并合并
        Map<String, List<MesShiftWorkSched>> shiftGroups = shiftWorkScheds.stream()
                .collect(Collectors.groupingBy(s -> s.getShiftName() != null ? s.getShiftName() : "默认班次"));
        
        for (Map.Entry<String, List<MesShiftWorkSched>> entry : shiftGroups.entrySet()) {
            Shift shift = new Shift();
            List<MesShiftWorkSched> schedList = entry.getValue();
            
            if (!schedList.isEmpty()) {
                MesShiftWorkSched firstSched = schedList.get(0);
                
                // 设置班次时间（需要根据实际字段调整）
                if (firstSched.getShiftStart() != null && firstSched.getShiftEnd() != null) {
                    shift.setStartTime(firstSched.getShiftStart().toLocalTime());
                    shift.setEndTime(firstSched.getShiftEnd().toLocalTime());
                } else {
                    // 默认24小时
                    shift.setStartTime(LocalTime.of(0, 0, 0));
                    shift.setEndTime(LocalTime.of(23, 59, 59));
                }
                
                // 设置工作日（需要根据实际字段调整）
                HashSet<Integer> days = new HashSet<>();
                for (int i = 0; i <= 6; i++) {
                    days.add(i);
                }
                shift.setDays(days);
            }
            
            shifts.add(shift);
        }
        
        return shifts.isEmpty() ? createDefault24HourShift(0L) : shifts;
    }

    /**
     * 深拷贝 GAScheduleResult 对象
     * 
     * @param source 源对象
     * @return 拷贝后的新对象
     */
    private GAScheduleResult copyGAScheduleResult(GAScheduleResult source) {
        if (source == null) {
            return null;
        }
        
        GAScheduleResult copy = new GAScheduleResult();
        
        // 拷贝基本字段
        copy.setGroupId(source.getGroupId());
        copy.setOperationId(source.getOperationId());
        copy.setExecId(source.getExecId());
        copy.setOrderId(source.getOrderId());
        copy.setOrderCode(source.getOrderCode());
        copy.setProductId(source.getProductId());
        copy.setProductName(source.getProductName());
        copy.setProductCode(source.getProductCode());
        copy.setMachineId(source.getMachineId());
        copy.setStartTime(source.getStartTime());
        copy.setEndTime(source.getEndTime());
        copy.setTeardownTime(source.getTeardownTime());
        copy.setQuantity(source.getQuantity());
        copy.setDesignatedStartTime(source.getDesignatedStartTime());
        copy.setLockStartTime(source.getLockStartTime());
        copy.setForcedMachineId(source.getForcedMachineId());
        copy.setIsLocked(source.isIsLocked());
        copy.setOneTime(source.getOneTime());
        copy.setProcessingTime(source.getProcessingTime());
        copy.setChangeOverTime(source.getChangeOverTime());
        copy.setPreTime(source.getPreTime());
        copy.setSeq(source.getSeq());
        copy.setBomTime(source.getBomTime());
        
        // 深拷贝 GeneDetails 列表
        if (source.getGeneDetails() != null) {
            List<ScheduleResultDetail> detailsCopy = new ArrayList<>();
            for (ScheduleResultDetail detail : source.getGeneDetails()) {
                ScheduleResultDetail detailCopy = new ScheduleResultDetail();
                detailCopy.setKey(detail.getKey());
                detailCopy.setStartTime(detail.getStartTime());
                detailCopy.setEndTime(detail.getEndTime());
                detailCopy.setOneTime(detail.getOneTime());
                detailCopy.setQuantity(detail.getQuantity());
                
                // 深拷贝 usedSegment
                if (detail.getUsedSegment() != null) {
                    List<com.aps.entity.basic.TimeSegment> segmentsCopy = new ArrayList<>(detail.getUsedSegment());
                    detailCopy.setUsedSegment(segmentsCopy);
                }
                
                detailsCopy.add(detailCopy);
            }
            copy.setGeneDetails(detailsCopy);
        }
        
        // 深拷贝 TargetFinishedOperationId 列表
        if (source.getTargetFinishedOperationId() != null) {
            copy.setTargetFinishedOperationId(new ArrayList<>(source.getTargetFinishedOperationId()));
        }
        
        return copy;
    }
    /**
     * 在排产前标记锁定期工单占用的设备时间段
     * 将锁定期工单占用的设备时间段标记为不可用，避免新工单与锁定期工单冲突
     * 核心逻辑：拆分设备的可用时间段，将锁定期工单占用的部分标记为isUsed=true
     * 
     * @param machines 设备列表
     * @param baseTime 基准时间
     */
    public void markLockedOrdersOccupiedTime(List<Machine> machines, LocalDateTime baseTime) {
        try {
            // 1. 获取时间配置
            LockPeriodConfig config = getLockPeriodConfig();
            if (config == null) {
                log.debug("未找到锁定期配置，跳过标记锁定期设备占用");
                return;
            }

            log.debug("开始标记锁定期设备占用时间段，锁定期范围: {} 到 {}", config.lockStartTime, config.lockEndTime);

            // 2. 从Dispatch表查询锁定期内的工单
            List<Dispatch> frozenDispatches = dispatchService.lambdaQuery()
                    .ge(Dispatch::getBeginTime, config.lockStartTime)
                    .le(Dispatch::getBeginTime, config.lockEndTime)
                    .eq(Dispatch::getIsDeleted, 0L)
                    .isNotNull(Dispatch::getEquipId)
                    .isNotNull(Dispatch::getBeginTime)
                    .isNotNull(Dispatch::getEndTime)
                    .list();

            if (frozenDispatches.isEmpty()) {
                log.debug("没有锁定期工单需要标记设备占用");
                return;
            }

            log.debug("查询到 {} 个锁定期工单，开始标记设备占用", frozenDispatches.size());

            // 3. 按设备分组
            Map<Long, List<Dispatch>> dispatchByMachine = frozenDispatches.stream()
                    .collect(Collectors.groupingBy(Dispatch::getEquipId));

            // 4. 为每个设备标记占用时间段
            int markedCount = 0;
            for (Map.Entry<Long, List<Dispatch>> entry : dispatchByMachine.entrySet()) {
                Long machineId = entry.getKey();
                List<Dispatch> dispatches = entry.getValue();

                // 查找对应的Machine对象
                Machine machine = machines.stream()
                        .filter(m -> m.getId() == machineId)
                        .findFirst()
                        .orElse(null);

                if (machine == null) {
                    log.warn("未找到设备 {}，跳过标记", machineId);
                    continue;
                }

                // 为该设备的每个锁定期工单创建占用时间段
                for (Dispatch dispatch : dispatches) {
                    LocalDateTime dispatchStart = dispatch.getBeginTime();
                    LocalDateTime dispatchEnd = dispatch.getEndTime();

                    // 只标记结束时间在baseTime之后的工单（这些会占用未来的设备时间）
                    if (dispatchEnd.isAfter(baseTime)) {
                        // 如果开始时间在baseTime之前，则从baseTime开始标记
                        LocalDateTime occupyStart = dispatchStart.isBefore(baseTime) ? baseTime : dispatchStart;
                        LocalDateTime occupyEnd = dispatchEnd;

                        // 初始化设备的可用时间段列表
                        if (machine.getAvailability() == null) {
                            machine.setAvailability(new CopyOnWriteArrayList<>());
                        }

                        // 关键逻辑：拆分设备的可用时间段
                        // 将与锁定期工单重叠的时间段拆分成三部分：
                        // 1. 锁定期之前的部分（isUsed=false）
                        // 2. 锁定期占用的部分（isUsed=true）
                        // 3. 锁定期之后的部分（isUsed=false）
                        splitAndMarkAvailabilitySegments(machine, occupyStart, occupyEnd);

                        markedCount++;
                        log.debug("标记设备 {} 的锁定期占用时间段: {} 到 {}, 订单: {}", 
                                machineId, occupyStart, occupyEnd, dispatch.getMesCode());
                    }
                }
            }

            log.debug("成功标记 {} 个锁定期工单的设备占用时间段", markedCount);
            
            // 5. 打印设备的可用时间段信息用于调试
            for (Machine machine : machines) {
                if (machine.getAvailability() != null && !machine.getAvailability().isEmpty()) {
                    log.debug("设备 {} 的availability中有 {} 个时间段，前3个:", machine.getId(), machine.getAvailability().size());
                    for (int i = 0; i < Math.min(3, machine.getAvailability().size()); i++) {
                        TimeSegment seg = machine.getAvailability().get(i);
                        log.debug("  [{}] 类型={}, 开始={}, 结束={}, isUsed={}", 
                            i, seg.getType(), seg.getStart(), seg.getEnd(), seg.isUsed());
                    }
                }
            }

        } catch (Exception e) {
            log.error("标记锁定期设备占用时间段失败: {}", e.getMessage(), e);
        }
    }

    /**
     * 拆分并标记设备的可用时间段
     * 将与锁定期工单重叠的时间段拆分，并标记占用部分为isUsed=true
     * 
     * @param machine 设备对象
     * @param occupyStart 锁定期工单开始时间
     * @param occupyEnd 锁定期工单结束时间
     */
    private void splitAndMarkAvailabilitySegments(Machine machine, LocalDateTime occupyStart, LocalDateTime occupyEnd) {
        if (machine.getAvailability() == null || machine.getAvailability().isEmpty()) {
            // 如果没有可用时间段，直接添加占用段
            TimeSegment occupiedSegment = new TimeSegment();
            occupiedSegment.setStart(occupyStart);
            occupiedSegment.setEnd(occupyEnd);
            occupiedSegment.setType(SegmentType.MAINTENANCE);
            occupiedSegment.setUsed(true);
            occupiedSegment.setHoliday(false);
            occupiedSegment.setEfficiency(1.0);
            machine.getAvailability().add(occupiedSegment);
            return;
        }

        // 处理现有的可用时间段
        List<TimeSegment> segmentsToProcess = new ArrayList<>(machine.getAvailability());
        machine.getAvailability().clear();

        for (TimeSegment segment : segmentsToProcess) {
            // 检查时间段与锁定期工单是否有重叠
            if (segment.getStart().isBefore(occupyEnd) && segment.getEnd().isAfter(occupyStart)) {
                // 有重叠，需要拆分

                // 1. 前半部分（锁定期之前）
                if (segment.getStart().isBefore(occupyStart)) {
                    TimeSegment beforeSegment = new TimeSegment();
                    beforeSegment.setStart(segment.getStart());
                    beforeSegment.setEnd(occupyStart);
                    beforeSegment.setType(segment.getType());
                    beforeSegment.setUsed(false);  // 未被占用
                    beforeSegment.setHoliday(segment.isHoliday());
                    beforeSegment.setEfficiency(segment.getEfficiency());
                    beforeSegment.setKey(segment.getKey());
                    machine.getAvailability().add(beforeSegment);
                    log.debug("添加前半部分时间段: {} 到 {}, isUsed=false", beforeSegment.getStart(), beforeSegment.getEnd());
                }

                // 2. 中间部分（锁定期占用）
                TimeSegment occupiedSegment = new TimeSegment();
                occupiedSegment.setStart(occupyStart);
                occupiedSegment.setEnd(occupyEnd);
                occupiedSegment.setType(SegmentType.MAINTENANCE);
                occupiedSegment.setUsed(true);  // 被占用
                occupiedSegment.setHoliday(false);
                occupiedSegment.setEfficiency(segment.getEfficiency());
                machine.getAvailability().add(occupiedSegment);
                log.debug("添加占用部分时间段: {} 到 {}, isUsed=true", occupiedSegment.getStart(), occupiedSegment.getEnd());

                // 3. 后半部分（锁定期之后）
                if (segment.getEnd().isAfter(occupyEnd)) {
                    TimeSegment afterSegment = new TimeSegment();
                    afterSegment.setStart(occupyEnd);
                    afterSegment.setEnd(segment.getEnd());
                    afterSegment.setType(segment.getType());
                    afterSegment.setUsed(false);  // 未被占用
                    afterSegment.setHoliday(segment.isHoliday());
                    afterSegment.setEfficiency(segment.getEfficiency());
                    afterSegment.setKey(segment.getKey());
                    machine.getAvailability().add(afterSegment);
                    log.debug("添加后半部分时间段: {} 到 {}, isUsed=false", afterSegment.getStart(), afterSegment.getEnd());
                }
            } else {
                // 没有重叠，保持原样
                segment.setUsed(false);  // 确保未被占用的段标记为false
                machine.getAvailability().add(segment);
                log.debug("保持原有时间段: {} 到 {}, isUsed=false", segment.getStart(), segment.getEnd());
            }
        }

        // 按开始时间排序
        machine.getAvailability().sort(Comparator.comparing(TimeSegment::getStart));
    }

    /**
     * 锁定期配置类
     */
    private static class LockPeriodConfig {
        LocalDateTime baseTime;
        long freezeSeconds;
        LocalDateTime lockStartTime;
        LocalDateTime lockEndTime;
    }

    /**
     * 锁定期工单数据类
     */
    private static class LockedOrdersData {
        List<GAScheduleResult> results = new ArrayList<>();
        Map<String, Entry> entries = new HashMap<>();
        Set<Long> machineIds = new HashSet<>();
    }
}
