package com.aps.service.Algorithm;


import com.aps.common.util.FileHelper;
import com.aps.common.util.GlobalCacheUtil;
import com.aps.common.util.redis.RedisUtils;
import com.aps.entity.*;
import com.aps.entity.Algorithm.*;
import com.aps.entity.Algorithm.IDAndChildID.GroupResult;
import com.aps.entity.basic.*;
import com.aps.mapper.RoutingHeaderMapper;
import com.aps.mapper.RoutingSupportingReplaceMapper;
import com.aps.mapper.RoutingsupportingMapper;
import com.aps.service.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * 作者：佟礼
 * 时间：2025-12-08
 */
@Service
public class MaterialRequirementService {

    private List< Material> _materials;


    @Autowired
    RoutingDetailConnectService routingDetailConnectService;

    @Autowired
    private RedisUtils redisUtils;


    @Autowired
    RoutingHeaderMapper routingHeaderMapper;

    @Autowired
    RoutingSupportingReplaceMapper routingSupportingReplaceMapper;

    @Autowired
    RoutingsupportingMapper routingsupportingMapper;

    @Autowired
    RoutingDataService _routingDataService;
    @Autowired
    private EquipinfoService equipinfoService;
    @Autowired
    private RoutingDiscreteParamService _routingDiscreteParamService;

    @Autowired
    private   LanuchService lanuchService;
    private  LocalDateTime baseTime ;
    @Autowired
    private  PlanResourceService planResourceService;
    @Autowired
    private  Equiptype1Service equiptype1Service;

    private GlobalParam globalParam;



    private static final int cachetimeout  = 60;
    private static final int ORACLE_IN_BATCH_SIZE = 1000;
    private String cacheKey="_MR_";
    private String routingHeaderCacheKey=cacheKey+ "RoutingHeader";
    private String routingsupportingCacheKey=cacheKey+ "Routingsupporting";
    private String routingSupportingReplaceCacheKey=cacheKey+ "RoutingSupportingReplace";

    private String routingDetailCacheKey=cacheKey+ "RoutingDetail";
    private String routingDetailEquipCacheKey=cacheKey+ "RoutingDetailEquip";

    private String routingDetailConnectCacheKey=cacheKey+ "RoutingDetailConnect";
    private String routingDiscreteParamCacheKey=cacheKey+ "RoutingDiscreteParam";

    private String materialsCacheKey=cacheKey+ "material";

    public Map<Integer,Object> preloadRoutingCache(String sceneId,LocalDateTime baseTime, List<Order> _orders,List<Material> materials,List<Entry> _allOperations,boolean isIsCheckSf) {

        this.baseTime=baseTime;
        Map<Integer,Object> reslte=new HashMap<>(2);
        reslte.put(1,null);
        reslte.put(2,null);
        this._materials=materials;
        List<Integer> routingIds=  _orders.stream()
                .filter(t->t.getRoutingId()!=null)
                .map(Order::getRoutingId)
                .distinct()
                .collect(Collectors.toList());
        List<RoutingHeader> routingHeaders = getRoutingHeadersByIds(routingIds);


        List<Routingsupporting> routingsupportings=null;
        //  查询并缓存Routingsupporting

        routingsupportings = getRoutingsupportingsByRoutingHeaderIds(routingIds);


        //  查询并缓存RoutingSupportingReplace
        List<RoutingSupportingReplace> replaces=null;
        if (routingsupportings != null && !routingsupportings.isEmpty()) {
            List<String> routingsupportingids = routingsupportings.stream()
                    .map(Routingsupporting::getStrId)
                    .distinct()
                    .collect(Collectors.toList());

            replaces = getRoutingSupportingReplacesByStrsupids(routingsupportingids);

        }
        List<Material> useMaterials=new ArrayList<>();
        Set<String> useMaterialids=new HashSet<>();

        if(routingsupportings!=null&&routingsupportings.size()>0)
        {
            List<String> materialIds=new ArrayList<>();
            for (Order order : _orders) {
                Integer routingid=order.getRoutingId();
                List<Routingsupporting> MaterialRequirements = routingsupportings.stream()
                        .filter(t -> t.getRoutingHeaderId().equals(routingid))
                        .collect(Collectors.toList());


                String orderId= order.getOrderId();
                if(MaterialRequirements!=null)
                {

                    List<Entry> Operations= _allOperations.stream().filter(t -> t.getOrderId() != null)
                            .filter(t->t.getOrderId().equals(orderId))
                            .collect(Collectors.toList());

                    for (Entry operation : Operations) {
                        List<Routingsupporting> MaterialRequirement_entrys = routingsupportings.stream()
                                .filter(t -> t.getRoutingDetailId().equals(operation.getRoutingDetailId()))
                                .collect(Collectors.toList());
                        List<OrderMaterialRequirement> materialRequirementList=new ArrayList<>();
                        if(MaterialRequirement_entrys!=null) {

                            for (Routingsupporting component : MaterialRequirement_entrys) {
                                // 查找物料（流式处理替代First）
                                String materialId = component.getMaterialId();
                                Material material = materials.stream()
                                        .filter(m -> m.getId().equals(materialId))
                                        .findFirst()
                                        .orElse(null);
                                if (material != null) {
                                    if (!useMaterialids.contains(materialId)) {
                                        useMaterials.add(material);
                                        useMaterialids.add(materialId);
                                    }
                                    if(component.getSpentQty()==null)
                                    {
                                        throw new RuntimeException("配套数据有问题，需求数量为空，请检查数据,"+component.getMaterialNumber());
                                    }
                                    double allneeded = component.getSpentQty().doubleValue()/ component.getMainQty().doubleValue() * operation.getQuantity();

                                    OrderMaterialRequirement orderMaterialRequirement = CreateMaterialRequirement(material, orderId, "", operation,
                                            allneeded,component.getSpentQty().doubleValue(), component.getMainQty().doubleValue(),operation.getQuantity(),baseTime);
                                    orderMaterialRequirement.setBomId(component.getStrId());
                                    if (!material.getMaterialTypeName().equals("MP") && isIsCheckSf) {
                                        materialIds.add(materialId);//半成品ID
                                    }
                                    materialRequirementList.add(orderMaterialRequirement);
                                }
                            }
                        }
                        operation.setMaterialRequirements(materialRequirementList);
                    }
                }
            }
            if(replaces!=null&&replaces.size()>0) {
                for (RoutingSupportingReplace routingSupportingReplace : replaces) {
                    String materialID1 = routingSupportingReplace.getMaterialid();
                    if (!useMaterialids.contains(materialID1)) {
                        Material material = _materials.stream()
                                .filter(m -> m.getId().equals(materialID1))
                                .findFirst()
                                .orElse(null);
                        if (material != null) {
                            useMaterials.add(material);
                            useMaterialids.add(materialID1);
                        }
                    }
                }
            }
            //半成品往下继续找
            if(materialIds!=null&&materialIds.size()>0)
            {
                Map<Integer,Object> reslte1=preloadSfRoutingBomCache(materialIds, routingHeaders, routingsupportings, replaces);
                List<Long> routingIds1=(List<Long>) reslte1.get(1);
                if(routingIds1!=null&&routingIds1.size()>0)
                {
                    List<Long> equipids=  preloadSfRoutingCache(sceneId,routingIds1);
                    reslte.put(1,equipids);
                }
                List<Material> useMaterials1=(List<Material>) reslte1.get(2);

                if(useMaterials1!=null) {
                    for (Material m:useMaterials1) {
                        String materialID1= m.getId();
                        if(!useMaterialids.contains(materialID1)) {
                            useMaterials.add(m);
                            useMaterialids.add(materialID1);
                        }
                    }
                }
            }
        }
        reslte.put(2,useMaterials);

        SaveBomCache(sceneId, routingHeaders, routingsupportings, replaces,useMaterials);

        return reslte;
    }



    private  Map<Integer,Object> preloadSfRoutingBomCache(List<String> materialIDs,List<RoutingHeader> headers,List<Routingsupporting> routingsupportings,List<RoutingSupportingReplace> routingsupportingreplaces) {

        Map<Integer,Object> reslte=new HashMap<>(2);
        reslte.put(1,null);
        reslte.put(2,null);
        List<Material> useMaterials=new ArrayList<>();
        Set<String> useMaterialids=new HashSet<>();
        List<Long> routingIds=new ArrayList<>();
        List<Long> routingIds1=new ArrayList<>();
        Long routingId = 0l;
        List<Routingsupporting> routingsupportings1 = new ArrayList<>();
        List<RoutingSupportingReplace> routingsupportingreplaces1 = new ArrayList<>();

        for (String materialID:materialIDs) {
            RoutingHeader headers1 = headers.stream()
                    .filter(t -> t.getMaterialId().equals(materialID))
                    .findFirst().orElse(null);
            if (headers1 == null) {
                LambdaQueryWrapper<RoutingHeader> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(RoutingHeader::getMaterialId, materialID)
                        .eq(RoutingHeader::getIsDeleted, 0);
                // .eq(RoutingHeader::getApprovalStatus, 1); // 添加 is_deleted=0 过滤条件
                headers1 = routingHeaderMapper.selectList(wrapper).stream().findFirst().orElse(null);
                if (headers1 != null) {
                    headers.add(headers1);
                    routingId = headers1.getId().longValue();
                    routingIds.add(routingId);
                }
            }else {
                routingIds1.add(headers1.getId().longValue());
            }
        }


        if (routingIds != null&&routingIds.size()>0) {



            routingsupportings1 = getRoutingsupportingsByRoutingHeaderIds(routingIds);
            if(routingsupportings1!=null&&routingsupportings1.size()>0)
            {
                routingsupportings.addAll(routingsupportings1);

                List<String> routingsupportingids = routingsupportings1.stream()
                        .map(Routingsupporting::getStrId)
                        .distinct()
                        .collect(Collectors.toList());

                routingsupportingreplaces1 = getRoutingSupportingReplacesByStrsupids(routingsupportingids);

                routingsupportingreplaces.addAll(routingsupportingreplaces1);

                List<String> materialIds=new ArrayList<>();
                for (Routingsupporting routingsupporting:routingsupportings1) {
                    String materialID1= routingsupporting.getMaterialId();
                    Material material = _materials.stream()
                            .filter(m -> m.getId().equals(materialID1))
                            .findFirst()
                            .orElse(null);
                    if (material != null) {
                        if(!useMaterialids.contains(materialID1)) {
                            useMaterials.add(material);
                            useMaterialids.add(materialID1);
                        }
                        if(!material.getMaterialTypeName().equals("MP")) {
                            materialIds.add(materialID1);
                        }
                    }
                }
                for (RoutingSupportingReplace routingSupportingReplace:routingsupportingreplaces1) {
                    String materialID1= routingSupportingReplace.getMaterialid();
                    if(!useMaterialids.contains(materialID1)) {
                        Material material = _materials.stream()
                                .filter(m -> m.getId().equals(materialID1))
                                .findFirst()
                                .orElse(null);
                        if (material != null) {
                            useMaterials.add(material);
                            useMaterialids.add(materialID1);
                        }
                    }
                }

                Map<Integer,Object> r1=preloadSfRoutingBomCache(materialIds, headers, routingsupportings, routingsupportingreplaces);
                List<Long> routingIds2=(List<Long>) r1.get(1);
                List<Material> useMaterials2=( List<Material>) r1.get(2);
                if(routingIds2!=null)
                {
                    routingIds.addAll(routingIds2);
                }
                if(useMaterials2!=null&&useMaterials2.size()>0) {
                    for (Material m:useMaterials2) {
                        String materialID1= m.getId();
                        if(!useMaterialids.contains(materialID1)) {
                            useMaterials.add(m);
                            useMaterialids.add(materialID1);
                        }
                    }
                }
            }
        }
        if(routingIds1!=null)
        {
            routingIds.addAll(routingIds1);
        }
        reslte.put(1,routingIds);
        reslte.put(2,useMaterials);
        return reslte;
    }


    private  List<Long> preloadSfRoutingCache(String sceneId,List<Long> routingIds) {


        List<RoutingDetail> RoutingDetails = null;
        List<RoutingDetailEquip> routingDetailEquips = null;
        List<RoutingDetailConnect> connections = null;
        List<RoutingDiscreteParam> routingDiscreteParams=null;

        if (routingIds != null || routingIds.size() > 0) {

            RoutingDetails = lanuchService.getRoutingDetails(routingIds);

            if (RoutingDetails == null && RoutingDetails.size() == 0) {
                return null;
            }

            routingDetailEquips = lanuchService.getRoutingDetailEquip(routingIds);

            List<Long> routingequipDetailIds = routingDetailEquips.stream()
                    .map(RoutingDetailEquip::getRoutingDetailId)
                    .distinct()
                    .collect(Collectors.toList());

            List<RoutingDetail> RoutingDetailsn=   RoutingDetails.stream()
                    .filter(t->!routingequipDetailIds.contains( t.getId()))
                    .collect(Collectors.toList());

            if (RoutingDetailsn != null && !RoutingDetailsn.isEmpty()) {

                List<Equiptype1> equipTypes = GetEquipTypes();

                Map<Long, Equiptype1> equipTypeMap = equipTypes.stream()
                        .collect(Collectors.toMap(Equiptype1::getId, Function.identity()));


                List<PlanResource> list =GetPlanResources();
                Map<Integer, PlanResource> planResourceByReferenceIdMap = list.stream()
                        .filter(pr -> pr.getReferenceId() != null)
                        .collect(Collectors.toMap(PlanResource::getReferenceId, Function.identity()));

                List<Equipinfo> equipinfo= GetEquipinfos();

                Map<Integer, Equipinfo> equipinfoMap = equipinfo.stream()
                        .collect(Collectors.toMap(Equipinfo::getId, Function.identity()));
                Map<Integer, List<Equipinfo>> equipinfoByEquipTypeMap = equipinfo.stream()
                        .filter(e -> e.getEquipType() != null)
                        .collect(Collectors.groupingBy(Equipinfo::getEquipType));

                for (RoutingDetail exec : RoutingDetailsn) {
                    try {
                        // 获取machineId
                        Long machineId = exec.getEquipTypeId();
                        if (machineId == null) {
                            continue;
                        }

                        // 使用Map快速查询设备列表
                        List<Equipinfo> matchedEquipments = equipinfoByEquipTypeMap.get(machineId.intValue());
                        if (matchedEquipments == null || matchedEquipments.isEmpty()) {

                            throw new RuntimeException(String.format("未找到machineId=%d对应的设备信息", machineId));

                        }

                        // 遍历所有匹配的设备，创建ProdEquipment对象
                        for (Equipinfo equipinfo1 : matchedEquipments) {
                            RoutingDetailEquip prodEquipment = new RoutingDetailEquip();

                            prodEquipment.setRoutingDetailId(exec.getId());
                            prodEquipment.setRoutingHeaderId(exec.getRoutingHeaderId());
                            // 使用Map快速查询，替代stream操作
                            PlanResource planResource = planResourceByReferenceIdMap.get(equipinfo1.getId());
                            if (planResource != null) {
                                prodEquipment.setEquipId(planResource.getId().longValue());
                            } else {
                                throw new RuntimeException(String.format("未找到equipinfoId=%d对应的planResource信息", equipinfo1.getId()));

                            }

                            prodEquipment.setName(equipinfo1.getEquipName());

                            // 使用Map快速查询
                            Equiptype1 equiptype1 = equipTypeMap.get(machineId);
                            if (equiptype1 != null) {
                                prodEquipment.setType1(equiptype1.getId());
                                prodEquipment.setTypeName(equiptype1.getEquipTypeId());

                            }
                            prodEquipment.setIsdeleted(0);
                            // 设置其他属性
                            prodEquipment.setEfficiencyValue(1.0); // 默认效率值
                            prodEquipment.setSetupTime(0); // 默认准备时间
                            prodEquipment.setDuration(exec.getRuntime());
                            prodEquipment.setOutputQuantity(exec.getSingleOut());



                            // 设置execId


                            routingDetailEquips.add(prodEquipment);
                        }
                    } catch (Exception e) {
                        throw e;
                    }
                }
            }


            LambdaQueryWrapper<RoutingDetailConnect> routingDetailConnectwrapper = new LambdaQueryWrapper<>();
            routingDetailConnectwrapper.in(RoutingDetailConnect::getRoutingHeaderId, routingIds)
                    .eq(RoutingDetailConnect::getIsdeleted, 0); // 添加 isdeleted=0 过滤条件

            connections = routingDetailConnectService.list(routingDetailConnectwrapper);


            List<Long> routingDetailIds = RoutingDetails.stream()
                    .map(RoutingDetail::getId)
                    .distinct()
                    .collect(Collectors.toList());

            routingDiscreteParams = _routingDiscreteParamService.lambdaQuery()
                    .in(RoutingDiscreteParam::getRoutingDetailId, routingDetailIds)
                    .eq(RoutingDiscreteParam::getIsDeleted, 0)
                    .list();


            SaveDetailCache(sceneId,RoutingDetails,routingDetailEquips,connections,routingDiscreteParams);

            if (routingDetailEquips != null && routingDetailEquips.size() > 0) {

                List<Long> equipIds = routingDetailEquips.stream()
                        .map(RoutingDetailEquip::getEquipId)
                        .distinct() // 提取Exec_ID
                        .collect(Collectors.toList());
                return equipIds;
            }
        }
        return null;
    }


    /**
     * 构建多级BOM需求网络
     * @return 所有物料需求列表
     */
    public List<OrderMaterialRequirement> buildMultiLevelRequirementNetwork(Chromosome chromosome,String sceneId, LocalDateTime _baseTime,GlobalParam _globalParam) {
        List<OrderMaterialRequirement> allRequirements = new ArrayList<>();
        List<Order> childorders = new ArrayList<>();
        List<Entry> _newEntrys = new ArrayList<>();


        List<Entry> allOperations=chromosome.getAllOperations();
        List<Order> orders=chromosome.getOrders();

        Map<Integer, Integer> orderProcessCounter = allOperations.stream()
                .collect(Collectors.groupingBy(Entry::getGroupId, Collectors.collectingAndThen(
                        Collectors.counting(), Long::intValue)))
                .entrySet().stream()
                .collect(Collectors.toMap(Map.Entry::getKey, e -> 0));

        List<Integer> operationSequencing= new ArrayList<>(chromosome.getOperationSequencing());
        orders.forEach(t->clearFinishOrder(t));


        for (Integer groupId : operationSequencing)
        {
            Order demand=orders.stream().filter(t->t.getId()==groupId).findFirst().orElse(null);
if(demand==null)
{
    continue;
}
            if (demand.getFinishOrderId() != null && !demand.getFinishOrderId().isEmpty()) {
                continue;
            }

            int scheduledCount = orderProcessCounter.get(groupId);
            List<Entry> orderOps = allOperations.stream()
                    .filter(t -> t.getGroupId() == groupId)
                    .sorted(Comparator.comparing(Entry::getSequence))
                    .collect(Collectors.toList());

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

            // 调用BuildOperationBOM方法（返回结果对象替代out参数）
            BOMBuildResult operationResult = buildOperationSFBOM(operation.getOrderId(), "",
                    operation.getQuantity(), operation, 1,demand,sceneId,chromosome,_baseTime,_globalParam);
//                // 合并物料需求和子订单
            if(operationResult!=null) {
                allRequirements.addAll(operationResult.getMaterialRequirements());
                childorders.addAll(operationResult.getChildOrders());
                _newEntrys.addAll(operationResult.getNewEntrys());
            }
            orderProcessCounter.put(groupId, orderProcessCounter.get(groupId) + 1);
        }



        // 将子订单添加到全局订单列表
        if (orders != null) {
            orders.addAll(childorders);
            // _allOperations.addAll(_newEntrys);
        }

        return allRequirements;
    }

    private void clearFinishOrder (Order order)
    {
        if (order.getFinishOrderId() == null) {
            order.setFinishOrderId(new ArrayList<>());
            order.setTargetFinishedOperationId(new ArrayList<>());
        }
    }

    /**
     * 构建订单BOM
     * @param parent 父项ID
     * @param materialID 物料ID
     * @param mainorderId 主订单ID
     * @param childorderId 子订单ID
     * @param parentQuantity 父项数量
     * @param level 层级
     * @return 包含物料需求列表和子订单列表的结果对象
     */
    public BOMBuildResult buildOrderBOM(String sceneId,int parent, String materialID, String mainorderId,
                                        String childorderId, double parentQuantity, int level,Order forder,int finishOpertionID,Chromosome chromosome, LocalDateTime baseTime, GlobalParam globalParam) {
        forder.setCreateBom(true);

        List<RoutingHeader>  headers=GetRoutingHeader(sceneId);
        RoutingHeader routingHeaders=  headers.stream()
                .filter(t->t.getId()==parent|| t.getMaterialId().equals(materialID))
                .findFirst()
                .orElse(null);
        List<RoutingHeader>  headers1;
        // 若未找到产品，返回空结果（根据业务可调整为抛出异常）
        if (routingHeaders==null) {
            return null;
        }

        List<OrderMaterialRequirement> materialRequirements = new ArrayList<>();
        List<Order> childorders2 = new ArrayList<>();
        List<Entry> _newEntrys = new ArrayList<>();
        List<Machine> _newMachines = new ArrayList<>();
        // 遍历产品的工序，递归构建工序BOM

        List<Entry> _allOperations= chromosome.getAllOperations();

        List<Entry> Operations= _allOperations.stream().filter(t -> t.getOrderId() != null)
                .filter(t->t.getOrderId().equals(childorderId))
                .collect(Collectors.toList());

        if (Operations != null) {
            for (Entry operation : Operations) {
                if(finishOpertionID!=0)
                {
                    if(operation.getTargetFinishedOperationId()==null)
                    {
                        operation.setTargetFinishedOperationId(new ArrayList<>());
                    }
                    operation.getTargetFinishedOperationId().add(finishOpertionID);
                }
                // 调用BuildOperationBOM方法（返回结果对象替代out参数）
                BOMBuildResult operationResult = buildOperationBOM(mainorderId, childorderId,
                        parentQuantity, operation, level,forder,sceneId,chromosome, baseTime, globalParam);
//                // 合并物料需求和子订单
                if(operationResult!=null) {
                    materialRequirements.addAll(operationResult.getMaterialRequirements());
                    childorders2.addAll(operationResult.getChildOrders());
                    _newEntrys.addAll(operationResult.getNewEntrys());
                }
            }
        }

        return new BOMBuildResult(materialRequirements, childorders2,_newEntrys);

    }
    /**
     * 构建工序BOM需求
     * @param orderId 主订单ID
     * @param childorderId 子订单ID
     * @param parentQuantity 父项数量
     * @param operation 工序对象
     * @param level 层级
     * @return 包含物料需求列表和子订单列表的结果对象（替代C#的out参数）
     */
    public BOMBuildResult buildOperationBOM(String orderId, String childorderId, double parentQuantity,
                                            Entry operation, int level,Order forder,String sceneId,Chromosome chromosome, LocalDateTime baseTime, GlobalParam globalParam) {
        List<OrderMaterialRequirement> materialRequirements = new ArrayList<>();
        List<Order> _childorders = new ArrayList<>();
        List<Entry> _newEntrys = new ArrayList<>();
        List<Machine> _newMachines = new ArrayList<>();

        List<Routingsupporting> routingsupportings=GetRoutingsupportings(sceneId);

        List<Routingsupporting> MaterialRequirements=  routingsupportings.stream()
                .filter(t->t.getRoutingDetailId().equals(operation.getRoutingDetailId()))
                .collect(Collectors.toList());
        List<Order> orders=chromosome.getOrders();
        if (MaterialRequirements != null&&MaterialRequirements.size()>0) {
            TreeMap<String, Material> _materials= GetMaterials(sceneId);
            for (Routingsupporting component : MaterialRequirements) {

                double allneeded =  component.getSpentQty().doubleValue()/ component.getMainQty().doubleValue() * parentQuantity;
                double needed = allneeded;

                // 查找物料（流式处理替代First）
                Material material = _materials.get(component.getMaterialId());
                if (material == null) {
                    return null;
                }

                OrderMaterialRequirement orderMaterial= CreateMaterialRequirement(material,orderId,childorderId,operation,allneeded,component.getSpentQty().doubleValue(), component.getMainQty().doubleValue() , parentQuantity, baseTime);
                orderMaterial.setLevel(level);
                orderMaterial.setBomId(component.getStrId());
                materialRequirements.add(orderMaterial);

                if (!orderMaterial.getMaterialTypeName().equals("MP") ) {

                    // 处理半成品/成品的现有订单
                    List<Order> orders2 = orders.stream()
                            .filter(t -> t.getMaterialId().equals(orderMaterial.getMaterialId())  && t.getSYQuantity() > 0)
                            .sorted(Comparator.comparing(Order::getDueDate))
                            .collect(Collectors.toList());

                    if (!orders2.isEmpty()) {
                        for (Order order : orders2) {
                            if (order.getFinishOrderId() == null) {
                                order.setFinishOrderId(new ArrayList<>());
                                order.setTargetFinishedOperationId(new ArrayList<>());
                            }
                            order.getFinishOrderId().add(forder.getId());
                            order.getTargetFinishedOperationId().add(operation.getId());

                            orderMaterial.getProductOrderID().add(order.getId());

                            double useq = Math.min(needed, order.getSYQuantity());
                            needed -= useq;
                            order.setSYQuantity(order.getSYQuantity() - useq);

                            //防止已经生成过一次
                            if (!order.isCreateBom()) {
                                // 递归构建BOM
                                int l = level + 1;

                                BOMBuildResult childResult = buildOrderBOM(sceneId,0, orderMaterial.getMaterialId(),
                                        orderId, order.getOrderId(),
                                        order.getQuantity(), l,order,operation.getId(),chromosome, baseTime, globalParam);
                                //   materialRequirements.addAll(childResult.getMaterialRequirements());
                                _childorders.addAll(childResult.getChildOrders());
                                _newEntrys.addAll(childResult.getNewEntrys());
                                operation.getDependentOnOrderIds().add(order.getId());
                            }

                            if (needed <= 0) {
                                break;
                            }
                        }
                    }

                    // 更新已配和缺件数量
                    orderMaterial.setYpQty(allneeded - needed);
                    orderMaterial.setQjQty(needed);

                    if (needed > 0&&globalParam.isIsCheckSf()) {
                        // 创建新的子订单
                        Order childorder = new Order();
                        String OrderId = UUID.randomUUID().toString().replace("-", "");

                        childorder.setOrderId(OrderId);
                        childorder.setMaterialId(orderMaterial.getMaterialId());
                        childorder.setMaterialCode(orderMaterial.getMaterialCode());
                        childorder.setMaterialName(orderMaterial.getMaterialName());
                        childorder.setOrderCode("M_"+orderMaterial.getMaterialCode());
                        childorder.setQuantity((int) orderMaterial.getQjQty());
                        childorder.setFinishOrderId(new ArrayList<>());
                        childorder.getFinishOrderId().add(forder.getId());
                        childorder.setNewSfCreate(true);
                        childorder.setTargetFinishedOperationId(new ArrayList<>());
                        childorder.getTargetFinishedOperationId().add(operation.getId());
                        childorder.setSerie(forder.getSerie());

                        childorder.setStartDate(forder.getStartDate());
                        childorder.setDueDate(forder.getDueDate());
                        childorder.setPriority(forder.getPriority());
                        childorder.setActualPriority(forder.getActualPriority());


                        Map<Integer, Object> list= CreateChild(sceneId,childorder,orderMaterial.getMaterialId(), operation.getId(),chromosome);
                        if(list==null)
                        {
                            continue;
                        }
                        _childorders.add(childorder);
                        List<Entry>  newentrys=(List<Entry>)list.get(1);
                        _newEntrys.addAll(newentrys);

                        orderMaterial.getProductOrderID().add(childorder.getId());
                        operation.getDependentOnOrderIds().add(childorder.getId());
                        // 递归构建BOM
                        int l = level + 1;
                        BOMBuildResult childResult = buildOrderBOM(sceneId,0, orderMaterial.getMaterialId(),
                                orderId, childorder.getOrderId(),
                                childorder.getQuantity(), l,childorder,0,chromosome, baseTime, globalParam);
                        //  materialRequirements.addAll(childResult.getMaterialRequirements());
                        _childorders.addAll(childResult.getChildOrders());
                        _newEntrys.addAll(childResult.getNewEntrys());
                    }
                }

            }
        }
        operation.setMaterialRequirements(materialRequirements);

        return new BOMBuildResult(materialRequirements, _childorders,_newEntrys);
    }


    private  Map<Integer, Object> CreateChild(String sceneId,  Order order,String materialID,int finishOpertionID,Chromosome chromosome)
    {

        Long  routingIds=0l;
        List<RoutingHeader> headers=GetRoutingHeader(sceneId);
        RoutingHeader headers1=  headers.stream()
                .filter(t->t.getMaterialId().equals(materialID))
                .findFirst().orElse(null);
        if(headers1==null)
        {
            return null;
        }
        routingIds=headers1.getId().longValue();


        Long headersid=routingIds;
        List<RoutingDetail> allRoutingDetails=GetRoutingDetails(sceneId);
        List<RoutingDetail> RoutingDetails=  allRoutingDetails.stream()
                .filter(t->t.getRoutingHeaderId().equals(headersid))
                .collect(Collectors.toList());

        List<RoutingDetailConnect> connections=null;
        if(RoutingDetails==null||RoutingDetails.size()==0) {
            return null;
        }
        List<RoutingDetailEquip> allroutingDetailEquips=GetRoutingDetailEquips(sceneId);
        List<RoutingDetailEquip> routingDetailEquips=  allroutingDetailEquips.stream()
                .filter(t->t.getRoutingHeaderId().equals(headersid))
                .collect(Collectors.toList());



        order.setRoutingId(headers1.getId());
        order.setRoutingCode(headers1.getCode());
        ProdLaunchOrder prodOrderMain= convertToLaunchOrder(order,sceneId);

        List<RoutingDetailEquip> finalRoutingDetailEquips = routingDetailEquips;

        Integer departmentId = headers1.getDepartmentId() != null ? headers1.getDepartmentId() : null;

        List<ProdProcessExec> processExecList = RoutingDetails.stream()
                .map(detail -> lanuchService.createProcessExec(prodOrderMain, detail, sceneId, finalRoutingDetailEquips, headers1))
                .collect(Collectors.toList());

        List<Equipinfo> equipinfoList=GetEquipinfos();

        List<ProdEquipment> ProdEquipmentList=  lanuchService.batchInsertEquipMent(routingDetailEquips, sceneId,processExecList,false,equipinfoList);



        Map<String, String> routingDetailIdToExecIdMap = processExecList.stream()
                .collect(Collectors.toMap(
                        exec -> exec.getRoutingDetailId() + "_" + exec.getOrderId(), // 复合键：工序ID_订单ID
                        ProdProcessExec::getExecId,
                        (existing, replacement) -> existing)); // 处理重复key的情况

        List<RoutingDetailConnect> allroutingDetailconnections=GetRoutingDetailConnect(sceneId);

        connections=  allroutingDetailconnections.stream()
                .filter(t->t.getRoutingHeaderId().equals(headersid))
                .collect(Collectors.toList());


        List<ProdOrderProcess>  ProdOrderProcesslist=  connections.stream()
                .map(connection -> lanuchService.createProcessRelation(prodOrderMain, connection, sceneId, routingDetailIdToExecIdMap))
                .collect(Collectors.toList());

        List<Long> routingDetailIds = RoutingDetails.stream()
                .map(RoutingDetail::getId)
                .distinct()
                .collect(Collectors.toList());
        List<RoutingDiscreteParam> allroutingDiscreteParams=GetRoutingDiscreteParam(sceneId);
        List<RoutingDiscreteParam> routingDiscreteParams=  allroutingDiscreteParams.stream()
                .filter(t->routingDetailIds.contains(t.getRoutingDetailId()))
                .collect(Collectors.toList());




        List<Order> ProdLaunchOrders=new ArrayList<>();
        ProdLaunchOrders.add(order);

        Map<Integer, Object> list=_routingDataService.CreateEntry( sceneId,  ProdEquipmentList,  ProdLaunchOrders, routingDiscreteParams, ProdOrderProcesslist, processExecList,chromosome.getOperatRel(),finishOpertionID );


        if(list.get(1)!=null)
        {
            chromosome.getAllOperations().addAll(new CopyOnWriteArrayList((List<Entry>)list.get(1)) );

            chromosome.setOperatRel(new CopyOnWriteArrayList((List<GroupResult>)list.get(2)));
        }
        Map<Integer, Object> rest=new HashMap<>();
        rest.put(1,list.get(1));

        return rest;
    }

    private ProdLaunchOrder convertToLaunchOrder(Order order, String sceneId) {
        try {
            ProdLaunchOrder launchOrder = new ProdLaunchOrder();
            launchOrder.setOrderId(order.getOrderId());
            launchOrder.setSceneId(sceneId);
            launchOrder.setSerie(order.getSerie());
            launchOrder.setCreateUser("GA");
            launchOrder.setMaterialCode(order.getMaterialCode());
            launchOrder.setMaterialName(order.getMaterialName());
//            launchOrder.setStartDate(order.get);
            launchOrder.setEndDate(order.getDueDate());
//            launchOrder.setOrderPriority(order.getPrioritry());
            launchOrder.setOrderPriority(order.getPriority());
            launchOrder.setQuantity(order.getQuantity());
            launchOrder.setMaterialId(order.getMaterialId());


            launchOrder.setRoutingId(order.getRoutingId());
            launchOrder.setRoutingCode("");


            return launchOrder;
        } catch (Exception e) {

            return null;
        }
    }



    /**
     * 构建工序BOM需求
     * @param orderId 主订单ID
     * @param childorderId 子订单ID
     * @param parentQuantity 父项数量
     * @param operation 工序对象
     * @param level 层级
     * @return 包含物料需求列表和子订单列表的结果对象（替代C#的out参数）
     */
    public BOMBuildResult buildOperationSFBOM(String orderId, String childorderId, double parentQuantity,
                                              Entry operation, int level,Order forder,String sceneId,Chromosome chromosome, LocalDateTime baseTime, GlobalParam globalParam) {
        List<OrderMaterialRequirement> materialRequirements = new ArrayList<>();
        List<Order> _childorders = new ArrayList<>();
        List<Entry> _newEntrys = new ArrayList<>();

        List<OrderMaterialRequirement> MaterialRequirements= operation.getMaterialRequirements();

        List<Order> orders=chromosome.getOrders();
        if(operation.getTargetFinishedOperationId()!=null)
        {
            operation.getTargetFinishedOperationId().clear();

        }
        if(operation.getDependentOnOrderIds()!=null)
        {

            operation.getDependentOnOrderIds().clear();
        }

        if (MaterialRequirements != null&&MaterialRequirements.size()>0) {
            for (OrderMaterialRequirement orderMaterial : MaterialRequirements) {
                orderMaterial.getProductOrderID().clear();
                double allneeded = orderMaterial.getRequiredQuantity();

                double needed = allneeded;

                // 查找物料（流式处理替代First）

                if (!orderMaterial.getMaterialTypeName().equals("MP") ) {

                    // 处理半成品/成品的现有订单
                    // 为什么要先找现有订单，绑定上，因为要把它排在成品工单前面，才能有时间
                    List<Order> orders2 = orders.stream()
                            .filter(t -> t.getMaterialId().equals(orderMaterial.getMaterialId())  && t.getSYQuantity() > 0)
                            .sorted(Comparator.comparing(Order::getDueDate))
                            .collect(Collectors.toList());

                    if (!orders2.isEmpty()) {
                        for (Order order : orders2) {
                            if (order.getFinishOrderId() == null) {
                                order.setFinishOrderId(new ArrayList<>());
                                order.setTargetFinishedOperationId(new ArrayList<>());
                            }
                            order.getFinishOrderId().add(forder.getId());
                            order.getTargetFinishedOperationId().add(operation.getId());

                            orderMaterial.getProductOrderID().add(order.getId());

                            double useq = Math.min(needed, order.getSYQuantity());
                            needed -= useq;
                            order.setSYQuantity(order.getSYQuantity() - useq);

                            //防止已经生成过一次
                            if (!order.isCreateBom()) {
                                // 递归构建BOM
                                int l = level + 1;

                                BOMBuildResult childResult = buildOrderBOM(sceneId,0, orderMaterial.getMaterialId(),
                                        orderId, order.getOrderId(),
                                        order.getQuantity(), l,order,operation.getId(),chromosome, baseTime, globalParam);
                                materialRequirements.addAll(childResult.getMaterialRequirements());
                                _childorders.addAll(childResult.getChildOrders());
                                _newEntrys.addAll(childResult.getNewEntrys());
                                operation.getDependentOnOrderIds().add(order.getId());
                            }

                            if (needed <= 0) {
                                break;
                            }
                        }
                    }

                    // 更新已配和缺件数量
                    orderMaterial.setYpQty(allneeded - needed);
                    orderMaterial.setQjQty(needed);

                    if (needed > 0&&globalParam.isIsCheckSf()) {
                        // 创建新的子订单
                        Order childorder = new Order();
                        String OrderId = UUID.randomUUID().toString().replace("-", "");

                        childorder.setOrderId(OrderId);
                        childorder.setMaterialId(orderMaterial.getMaterialId());
                        childorder.setMaterialCode(orderMaterial.getMaterialCode());
                        childorder.setMaterialName(orderMaterial.getMaterialName());
                        childorder.setOrderCode("M_"+orderMaterial.getMaterialCode());
                        childorder.setQuantity((int) orderMaterial.getQjQty());
                        childorder.setFinishOrderId(new ArrayList<>());
                        childorder.getFinishOrderId().add(forder.getId());
                        childorder.setNewSfCreate(true);
                        childorder.setTargetFinishedOperationId(new ArrayList<>());
                        childorder.getTargetFinishedOperationId().add(operation.getId());
                        childorder.setSerie(forder.getSerie());

                        childorder.setStartDate(forder.getStartDate());
                        childorder.setDueDate(forder.getDueDate());
                        childorder.setPriority(forder.getPriority());
                        childorder.setActualPriority(forder.getActualPriority());


                        Map<Integer, Object> list= CreateChild(sceneId,childorder,orderMaterial.getMaterialId(), operation.getId(),chromosome);
                        if(list==null)
                        {
                            continue;
                        }
                        _childorders.add(childorder);
                        List<Entry>  newentrys=(List<Entry>)list.get(1);
                        _newEntrys.addAll(newentrys);

                        orderMaterial.getProductOrderID().add(childorder.getId());
                        operation.getDependentOnOrderIds().add(childorder.getId());
                        // 递归构建BOM
                        int l = level + 1;
                        BOMBuildResult childResult = buildOrderBOM(sceneId,0, orderMaterial.getMaterialId(),
                                orderId, childorder.getOrderId(),
                                childorder.getQuantity(), l,childorder,0,chromosome, baseTime, globalParam);
                        materialRequirements.addAll(childResult.getMaterialRequirements());
                        _childorders.addAll(childResult.getChildOrders());
                        _newEntrys.addAll(childResult.getNewEntrys());
                    }
                }
            }
        }

        return new BOMBuildResult(materialRequirements, _childorders,_newEntrys);
    }

    private OrderMaterialRequirement MaterialStock(Material material,String materialId,String orderId, String childorderId, int operationId,double allneeded, double needed,LocalDateTime earliestStartTime, boolean commitChanges ) {

        OrderMaterialRequirement orderMaterial = new OrderMaterialRequirement();
        orderMaterial.setOrderId(orderId);
        orderMaterial.setOperationId(operationId);
        orderMaterial.setChildOrderId(StringUtils.isBlank(childorderId) ? orderId : childorderId);
        orderMaterial.setRequiredQuantity(allneeded);
        orderMaterial.setQjQty(allneeded);
        orderMaterial.setMaterialCode(material.getCode());
        orderMaterial.setMaterialName(material.getName());
        orderMaterial.setMaterialTypeName(material.getMaterialTypeName());
        orderMaterial.setMaterialId(material.getId());
        double useStock=0;
        // 扣减现有库存
        List<Stock> stocks= material.getMaterialStocks().stream()
                .filter(t -> isStockValid(t, earliestStartTime) && t.getAvailableInventory() > 0)
                .sorted(Comparator.comparing(Stock::getExpiryDate, Comparator.nullsLast(LocalDateTime::compareTo))
                        .thenComparing(Stock::getWarehousingDate, Comparator.nullsLast(LocalDateTime::compareTo)))
                .collect(Collectors.toList());
        if(stocks!=null)
        {
            for (Stock s:stocks) {
                double useStock1 = Math.min(needed,s.getAvailableInventory());
                needed -=useStock1;
                useStock+=useStock1;
                if(commitChanges) {
                    s.setUsedInventory(s.getUsedInventory()+useStock1);
                }
                if(needed==0)
                {
                    break;
                }
            }
        }

        orderMaterial.setYpQty(useStock);

        orderMaterial.setUseStock(useStock);

        return orderMaterial;
    }

    private boolean isStockValid(Stock stock, LocalDateTime demandTime) {
        return stock.getExpiryDate() == null || !stock.getExpiryDate().isBefore(demandTime);
    }

    private void resetRequirementCalc(OrderMaterialRequirement orderMaterial) {
        orderMaterial.setUseStock(0);
        orderMaterial.setUseTransit(0);
       // orderMaterial.setArrivalTime(null);



        orderMaterial.setPurchaseStartTime(baseTime);
        orderMaterial.setPurchaseEndTime(baseTime.plusDays(orderMaterial.getPurchaseTime()));

        orderMaterial.setUseTime(baseTime.plusDays(orderMaterial.getPurchaseTime()+orderMaterial.getCheckLeadTime()));




        if (orderMaterial.getReplaceMaterial() != null && !orderMaterial.getReplaceMaterial().isEmpty()) {
            for (OrderMaterialRequirement replace : orderMaterial.getReplaceMaterial()) {
                replace.setUseStock(0);
                replace.setUseTransit(0);

           }
        }
    }


    private OrderMaterialRequirement CreateMaterialRequirement(Material material,String orderId, String childorderId, Entry operation,double need,double spentQty,double mainQty,double qty, LocalDateTime baseTime) {

        OrderMaterialRequirement orderMaterial = new OrderMaterialRequirement();
        orderMaterial.setOrderId(orderId);
        orderMaterial.setOperationId(operation.getId());
        orderMaterial.setChildOrderId(StringUtils.isBlank(childorderId) ? orderId : childorderId);
        orderMaterial.setMaterialCode(material.getCode());
        orderMaterial.setMaterialName(material.getName());
        orderMaterial.setMaterialTypeName(material.getMaterialTypeName());
        orderMaterial.setMaterialId(material.getId());
        orderMaterial.setCheckLeadTime(0);
        orderMaterial.setPurchaseTime(0);
        orderMaterial.setRequiredQuantity(need);
        orderMaterial.setQjQty(need);
        orderMaterial.setSpentQty(spentQty);
        orderMaterial.setMainQty(mainQty);
        orderMaterial.setQuantity(qty);

        List<MaterialPurchase> materialPurchaseList=material.getMaterialPurchases();
        if(materialPurchaseList!=null&&materialPurchaseList.size()>0)
        {
            Optional<MaterialPurchase> maxItem = materialPurchaseList.stream()
                    // 按purchaseCycle+inspectionCycle降序排序
                    .max((o1, o2) -> {
                        // 计算第一个对象的和（空值处理，避免空指针）
                        int sum1 = (o1.getPurchaseCycle() == null ? 0 : o1.getPurchaseCycle())
                                + (o1.getInspectionCycle() == null ? 0 : o1.getInspectionCycle());
                        // 计算第二个对象的和
                        int sum2 = (o2.getPurchaseCycle() == null ? 0 : o2.getPurchaseCycle())
                                + (o2.getInspectionCycle() == null ? 0 : o2.getInspectionCycle());
                        return Integer.compare(sum1, sum2);
                    });
            if (maxItem.isPresent()) {
                MaterialPurchase result = maxItem.get();

                orderMaterial.setPurchaseTime(result.getPurchaseCycle());
                orderMaterial.setCheckLeadTime(result.getInspectionCycle());
            }
        }
        orderMaterial.setUseTime(baseTime.plusDays(orderMaterial.getPurchaseTime()+orderMaterial.getCheckLeadTime()));

        return orderMaterial;
    }

    /**
     * 构建工序BOM需求

     * @param operation 工序对象

     * @return 包含物料需求列表和子订单列表的结果对象（替代C#的out参数）
     */
    public void EditOperationBOM(Entry operation,Chromosome chromosome,LocalDateTime earliestStartTime,GeneticDecoder coder,Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,Map<Integer, Entry> entryIndexById,Map<Integer, GAScheduleResult> scheduleIndexById, LocalDateTime baseTime,boolean isCheckMp) {
        EditOperationBOM(operation, chromosome, earliestStartTime, coder, machineTasksCache, entryIndexById, scheduleIndexById, baseTime, true,isCheckMp);
    }

    public void EditOperationBOM(Entry operation,Chromosome chromosome,LocalDateTime earliestStartTime,GeneticDecoder coder,Map<Long, CopyOnWriteArrayList<GAScheduleResult>> machineTasksCache,Map<Integer, Entry> entryIndexById,Map<Integer, GAScheduleResult> scheduleIndexById, LocalDateTime baseTime, boolean commitChanges,boolean isCheckMp) {
        List<OrderMaterialRequirement> materialRequirements = new ArrayList<>();

        String sceneId=chromosome.getScenarioID();
        Random rnd = new Random();
        List<OrderMaterialRequirement> MaterialRequirements=  operation.getMaterialRequirements();

        MaterialRequirements = MaterialRequirements.stream()
                .sorted((a, b) -> {
                    // 定义判断条件：是否满足 非MP + 生产订单ID非空非空串
                    boolean aMatch = !"MP".equals(a.getMaterialTypeName())
                            && a.getProductOrderID() != null && !a.getProductOrderID().isEmpty();
                    boolean bMatch = !"MP".equals(b.getMaterialTypeName())
                            && b.getProductOrderID() != null && !b.getProductOrderID().isEmpty();

                    // 排序规则：满足的排前面，不满足的排后面；都满足/都不满足则保持原序
                    if (aMatch && !bMatch) return -1;  // a满足b不满足，a在前
                    if (!aMatch && bMatch) return 1;   // a不满足b满足，b在前
                    return 0;                          // 同状态，保持原序
                })
                .collect(Collectors.toList());

        TreeMap<String, Material> materials=chromosome.getMaterials();
        List<OrderMaterialRequirement> remove=new ArrayList<>();
        Map<String, OrderMaterialRequirement> totalNeededByMaterial = new HashMap<>();

        if (MaterialRequirements != null&&MaterialRequirements.size()>0) {
            for (OrderMaterialRequirement orderMaterial : MaterialRequirements) {


                double allneeded = orderMaterial.getSpentQty() / orderMaterial.getMainQty() * operation.getQuantity();
                orderMaterial.setRequiredQuantity(allneeded);
                orderMaterial.setQjQty(allneeded);

                totalNeededByMaterial.put(orderMaterial.getMaterialId(),orderMaterial);
            }
        }

        CalBom(chromosome,operation.getId(), totalNeededByMaterial,materials,earliestStartTime,commitChanges,remove,null,false,isCheckMp);

                if (commitChanges && remove != null&&remove.size()>0) {
            //删除先删排产结果，然后记录orderID,到排产方案里，最后一起删除
            for (OrderMaterialRequirement mr:remove) {
                List<Integer> orderids= mr.getProductOrderID();
                if(orderids!=null&&orderids.size()>0) {
                    for (Integer orderid : orderids) {
                        coder.DelOrder(chromosome, orderid,mr);
                    }
                }
            }
            MaterialRequirements.removeAll(remove);
        }
    }

    public LocalDateTime CalBom(Chromosome chromosome,int operationId,Map<String, OrderMaterialRequirement> MaterialRequirements,TreeMap<String, Material> materials,LocalDateTime earliestStartTime,boolean commitChanges,List<OrderMaterialRequirement> remove,Map<Integer, List<Entry>> entrysBygroupId,boolean isSf,boolean isCheckMp)
    {

        String sceneId=chromosome.getScenarioID();
        Random rnd = new Random();
        LocalDateTime useTime1 = earliestStartTime;
        if (MaterialRequirements != null&&MaterialRequirements.size()>0) {
           for( Map.Entry<String, OrderMaterialRequirement> entry : MaterialRequirements.entrySet()) {
               OrderMaterialRequirement orderMaterial = entry.getValue();


               double allneeded = orderMaterial.getRequiredQuantity();
               double needed = allneeded;
               resetRequirementCalc(orderMaterial);

               // 查找物料（流式处理替代First）
               Material material = materials.get(orderMaterial.getMaterialId());
               if (material == null) {
                   return useTime1;
               }

               double useStock = 0;

               List<Stock> stocks = material.getMaterialStocks().stream()
                       .filter(t -> isStockValid(t, earliestStartTime) && t.getAvailableInventory() > 0)
                       .sorted(Comparator.comparing(Stock::getExpiryDate, Comparator.nullsLast(LocalDateTime::compareTo))
                               .thenComparing(Stock::getWarehousingDate, Comparator.nullsLast(LocalDateTime::compareTo)))
                       .collect(Collectors.toList());
               if (stocks != null) {
                   for (Stock s : stocks) {
                       double useStock1 = Math.min(needed, s.getAvailableInventory());
                       needed -= useStock1;
                       useStock += useStock1;
                       if (commitChanges) {
                           s.setUsedInventory(s.getUsedInventory() + useStock1);
                       }
                       orderMaterial.setUseStock(useStock);

                       if (needed == 0) {
                           break;
                       }
                   }
               }
             //  FileHelper.writeLogFile("BOM:"+material.getCode());
               if (needed <= 0) {
                   orderMaterial.setYpQty(allneeded - needed);
                   orderMaterial.setQjQty(needed);
                   orderMaterial.setUseTime(baseTime);
                   orderMaterial.setPurchaseStartTime(baseTime);
                   orderMaterial.setPurchaseEndTime(baseTime);
                   if (commitChanges) {
                       remove.add(orderMaterial);
                   }
                   if (isSf) {
                       if (!material.getMaterialTypeName().equals("MP")) {
                           List<Integer> orderids = orderMaterial.getProductOrderID();

                           for (Integer orderid : orderids) {

                               EditOrderOperation(chromosome, orderid, needed, entrysBygroupId);
                           }
                       }
                   }
                   continue;
               }
               List<RoutingSupportingReplace> routingsupportingreplaces = GetRoutingSupportingReplaces(sceneId);
               List<RoutingSupportingReplace> routingsupportingreplaces2 = null;
               if (routingsupportingreplaces != null && routingsupportingreplaces.size() > 1) {
                   routingsupportingreplaces2 = routingsupportingreplaces.
                           stream()
                           .filter(t -> t.getStrsupid().equals(orderMaterial.getBomId())
                                   && t.getMaterialid().equals(orderMaterial.getMaterialId())
                                   && !t.getTargetmaterialid().equals(orderMaterial.getMaterialId()))
                           .collect(Collectors.toList());
                   if (routingsupportingreplaces2 != null && routingsupportingreplaces2.size() > 0) {
                       for (RoutingSupportingReplace rsr : routingsupportingreplaces2) {

                           Material material1 = materials.get(rsr.getTargetmaterialid());
                          // FileHelper.writeLogFile("RoutingSupportingReplace:"+material1.getCode());
                           if (material1 == null) {
                               break;
                           }
                         //  FileHelper.writeLogFile("RoutingSupportingReplace: "+(commitChanges?"1":"0")+" " +material1.getCode()+": "+useStock);

                           OrderMaterialRequirement orderMaterial1 = MaterialStock(material1, rsr.getTargetmaterialid(), orderMaterial.getOrderId(), orderMaterial.getChildOrderId(), operationId, allneeded, needed, earliestStartTime, commitChanges);
                           if (orderMaterial1 != null) {
                               useStock = orderMaterial1.getUseStock();


                               needed -= useStock;
                              // FileHelper.writeLogFile("RoutingSupportingReplace: "+(commitChanges?"1":"0")+" " +material1.getCode()+": "+useStock);
                               orderMaterial.setUseStock(orderMaterial.getUseStock() + useStock);
                               orderMaterial.getReplaceMaterial().add(orderMaterial1);
                               if (needed <= 0) {
                                   break;
                               }

                           }
                       }
                   }

               }
               if (needed <= 0) {
                   orderMaterial.setYpQty(allneeded - needed);
                   orderMaterial.setQjQty(needed);
                   orderMaterial.setUseTime(baseTime);
                   orderMaterial.setPurchaseStartTime(baseTime);
                   orderMaterial.setPurchaseEndTime(baseTime);
                   if (commitChanges) {
                       remove.add(orderMaterial);
                   }
                   if (isSf) {
                       if (!material.getMaterialTypeName().equals("MP")) {
                           List<Integer> orderids = orderMaterial.getProductOrderID();

                           for (Integer orderid : orderids) {

                               EditOrderOperation(chromosome, orderid, needed, entrysBygroupId);
                           }
                       }
                   }
                   continue;
               }

               MaterialInTransit(material, "", orderMaterial, needed, earliestStartTime, materials, commitChanges,isCheckMp);

               needed -= orderMaterial.getUseTransit();

               if (routingsupportingreplaces2 != null && routingsupportingreplaces2.size() > 1) {
                   for (RoutingSupportingReplace rsr : routingsupportingreplaces2) {

                       OrderMaterialRequirement orderMaterial1 = orderMaterial.getReplaceMaterial().stream()
                               .filter(t -> t.getMaterialId().equals(rsr.getTargetmaterialid()))
                               .findFirst()
                               .orElse(null);

                       Material material1 = materials.get(orderMaterial1.getMaterialId())
                              ;
                       if (material1 == null) {
                           break;
                       }

                       MaterialInTransit(material1, rsr.getMaterialid(), orderMaterial1, needed, earliestStartTime, materials, commitChanges,isCheckMp);


                       needed -= orderMaterial1.getUseTransit();

                       if (orderMaterial.getArrivalTime() != null && orderMaterial1.getArrivalTime() != null) {
                           LocalDateTime earliestTime = orderMaterial.getArrivalTime().compareTo(orderMaterial1.getArrivalTime()) > 0 ? orderMaterial.getArrivalTime() : orderMaterial1.getArrivalTime();

                           orderMaterial.setArrivalTime(earliestTime);
                           orderMaterial.setUseTransit(orderMaterial.getUseTransit() + orderMaterial1.getUseTransit());

                       } else if (orderMaterial.getArrivalTime() != null) {
                           LocalDateTime earliestTime = orderMaterial.getArrivalTime();

                           orderMaterial.setArrivalTime(earliestTime);
                           orderMaterial.setUseTransit(orderMaterial.getUseTransit() + orderMaterial1.getUseTransit());

                       } else if (orderMaterial1.getArrivalTime() != null) {
                           LocalDateTime earliestTime = orderMaterial1.getArrivalTime();

                           orderMaterial.setArrivalTime(earliestTime);
                           orderMaterial.setUseTransit(orderMaterial.getUseTransit() + orderMaterial1.getUseTransit());

                       }


                       if (needed <= 0) {
                           break;
                       }
                   }
               }

               if (needed <= 0) {
                   orderMaterial.setYpQty(allneeded - needed);
                   orderMaterial.setQjQty(needed);
                   orderMaterial.setUseTime(orderMaterial.getArrivalTime());
                   orderMaterial.setPurchaseStartTime(baseTime);
                   orderMaterial.setPurchaseEndTime(baseTime);
                   if (commitChanges) {
                       remove.add(orderMaterial);
                   }
                   if (isSf) {
                       if (!material.getMaterialTypeName().equals("MP")) {
                           List<Integer> orderids = orderMaterial.getProductOrderID();

                           for (Integer orderid : orderids) {

                               EditOrderOperation(chromosome, orderid, needed, entrysBygroupId);
                           }
                       }
                   }
                   continue;
               }
               if (needed > 0) {
                   orderMaterial.setYpQty(allneeded - needed);
                   orderMaterial.setQjQty(needed);

                   if (material.getMaterialTypeName().equals("MP")) {
                       // 处理原材料采购时间
                       orderMaterial.setPurchaseStartTime(baseTime);
                       // 采购结束时间 = 采购开始时间 + 采购提前期（天）


                       List<MaterialPurchase> materialPurchaseList = material.getMaterialPurchases();
                       if (materialPurchaseList != null && materialPurchaseList.size() > 0) {

                           if(isCheckMp)
                           {
                               int randomSeq = rnd.nextInt(materialPurchaseList.size());

                               MaterialPurchase result = materialPurchaseList.get(randomSeq);

                               orderMaterial.setPurchaseTime(result.getPurchaseCycle());
                               orderMaterial.setCheckLeadTime(result.getInspectionCycle());
                               LocalDateTime purchaseEndTime = baseTime.plusDays(orderMaterial.getPurchaseTime() + orderMaterial.getCheckLeadTime());
                               orderMaterial.setPurchaseEndTime(purchaseEndTime);
                           }else {
                               orderMaterial.setPurchaseTime(0);
                               orderMaterial.setCheckLeadTime(0);
                               orderMaterial.setPurchaseEndTime(baseTime);
                           }
                       }

                   } else {
                       // 处理半成品/成品的现有订单

                       List<Integer> orderids = orderMaterial.getProductOrderID();
                       if (orderids != null && orderids.size() > 0) {

                           if (isSf) {
                               for (Integer orderid : orderids) {

                                   EditOrderOperation(chromosome, orderid, needed, entrysBygroupId);
                               }
                           }

                       } else {
                           List<MaterialPurchase> materialPurchaseList = material.getMaterialPurchases();
                           if (materialPurchaseList != null && materialPurchaseList.size() > 0) {
                               if(isCheckMp) {
                                   int randomSeq = rnd.nextInt(materialPurchaseList.size());

                                   MaterialPurchase result = materialPurchaseList.get(randomSeq);

                                   orderMaterial.setPurchaseTime(result.getPurchaseCycle());
                                   orderMaterial.setCheckLeadTime(result.getInspectionCycle());
                                   LocalDateTime purchaseEndTime = baseTime.plusDays(orderMaterial.getPurchaseTime() + orderMaterial.getCheckLeadTime());
                                   orderMaterial.setPurchaseEndTime(purchaseEndTime);
                               }else {
                                   orderMaterial.setPurchaseTime(0);
                                   orderMaterial.setCheckLeadTime(0);
                                   orderMaterial.setPurchaseEndTime(baseTime);
                               }
                           }
                       }
                   }
                   if (commitChanges) {
                       orderMaterial.getReplaceMaterial().removeIf(t -> t.getUseStock() == 0 && t.getUseTransit() == 0);
                   }
               }

               // 计算预计可用时间
               LocalDateTime arrivalTime = orderMaterial.getArrivalTime();
               LocalDateTime purchaseEndTime = orderMaterial.getPurchaseEndTime();
               LocalDateTime useTime = null;

               if (arrivalTime == null) {
                   useTime = purchaseEndTime;
               } else {
                   if (purchaseEndTime != null && purchaseEndTime.isAfter(arrivalTime)) {
                       useTime = purchaseEndTime;
                   } else {
                       useTime = arrivalTime;
                   }
               }
               useTime1 = useTime.compareTo(useTime1) > 0 ? useTime1 : useTime;
               orderMaterial.setUseTime(useTime);
               if(commitChanges)
               {
                   if(!isCheckMp)
                   {
                       orderMaterial.setPurchaseTime(0);
                       orderMaterial.setCheckLeadTime(0);
                   }

                   orderMaterial.setUseTime(earliestStartTime);
                   orderMaterial.setPurchaseEndTime(earliestStartTime.plusDays(-orderMaterial.getCheckLeadTime()));
                   orderMaterial.setPurchaseStartTime(orderMaterial.getPurchaseEndTime().plusDays(-orderMaterial.getPurchaseTime()));
               }
           }
        }
        return useTime1;
    }

    public void EditOrderOperation(Chromosome chromosome, int groupId,double needed,Map<Integer, List<Entry>> entrysBygroupId) {



      Order order=  chromosome.getOrders().stream()
                .filter(m -> m.getId()==groupId)
                .findFirst()
                .orElse(null);
               if(order!=null) {
                   if (needed == order.getQuantity()) {
                       return;
                   }else {
                       order.setQuantity(needed);
                   }
               }


        List<Entry> orderOps = entrysBygroupId.get(groupId);
               if(orderOps!=null) {
                   for (Entry currentOp : orderOps) {
                       if (!currentOp.isNewCreate()) {

                           break;
                       }
                       currentOp.setQuantity(needed);
                       if(currentOp.getMaterialRequirements()!=null) {
                           for (OrderMaterialRequirement orderMaterial : currentOp.getMaterialRequirements()) {
                               List<Integer> orderids = orderMaterial.getProductOrderID();
                               if (orderids != null && orderids.size() > 0) {
                                   for (Integer orderid : orderids) {
                                       double allneeded = orderMaterial.getSpentQty() / orderMaterial.getMainQty() * currentOp.getQuantity();

                                       EditOrderOperation(chromosome, orderid,allneeded,entrysBygroupId);
                                   }
                               }
                           }
                       }
                   }

               }

    }




    private void MaterialInTransit(Material material,String materialId, OrderMaterialRequirement orderMaterial, double needed,LocalDateTime earliestStartTime, TreeMap<String, Material> materials, boolean commitChanges,boolean isCheckMp ){

        // 处理在途物料
        LocalDateTime earliestTime = null;
        double useTransit = 0;
        if (material == null) {
            material = materials.get(materialId);
            if (material == null) {
                return ;
            }
        }
        LocalDateTime purchaseEndTime=baseTime;
        List<MaterialPurchase> materialPurchaseList = material.getMaterialPurchases();
        if (materialPurchaseList != null && materialPurchaseList.size() > 0) {
            if(isCheckMp) {

                Optional<MaterialPurchase> maxItem = materialPurchaseList.stream()
                        // 按purchaseCycle+inspectionCycle降序排序
                        .max((o1, o2) -> {
                            // 计算第一个对象的和（空值处理，避免空指针）
                            int sum1 = (o1.getPurchaseCycle() == null ? 0 : o1.getPurchaseCycle())
                                    + (o1.getInspectionCycle() == null ? 0 : o1.getInspectionCycle());
                            // 计算第二个对象的和
                            int sum2 = (o2.getPurchaseCycle() == null ? 0 : o2.getPurchaseCycle())
                                    + (o2.getInspectionCycle() == null ? 0 : o2.getInspectionCycle());
                            return Integer.compare(sum1, sum2);
                        });
                if (maxItem.isPresent()) {
                    MaterialPurchase result = maxItem.get();

                    purchaseEndTime = baseTime.plusDays(result.getPurchaseCycle() + result.getInspectionCycle());

                }
            }
        }
        LocalDateTime purchaseEndTime1=purchaseEndTime;
        // 按到货时间排序在途物料
        List<MaterialSupply> sortedInTransit = material.getInTransit().stream()
                .filter(t -> t.getQuantity() > 0&&purchaseEndTime1.compareTo(t.getArrivalTime())>=0)
                .sorted(Comparator.comparing(MaterialSupply::getArrivalTime, Comparator.nullsLast(LocalDateTime::compareTo)))
                .collect(Collectors.toList());

        if(sortedInTransit!=null&&sortedInTransit.size()>0) {
            for (MaterialSupply supply : sortedInTransit) {
                double useq = Math.min(needed, supply.getQuantity());
                if (useq <= 0) {
                    continue;
                }
                useTransit += useq;
                needed -= useq;
                if (commitChanges) {
                    supply.setQuantity(supply.getQuantity() - useq);
                }
                if (earliestTime == null || (supply.getArrivalTime() != null && supply.getArrivalTime().isAfter(earliestTime))) {
                    earliestTime = supply.getArrivalTime();
                }
                if (needed <= 0) {
                    break;
                }
            }
        }
        orderMaterial.setUseTransit(useTransit);
        orderMaterial.setArrivalTime(earliestTime);

    }
    private void  SaveBomCache(String sceneId,List<RoutingHeader> routingHeaders,List<Routingsupporting> routingsupportings,List<RoutingSupportingReplace> replaces,List<Material> useMaterials)
    {
        redisUtils.set(sceneId+routingHeaderCacheKey,routingHeaders);
        GlobalCacheUtil.put(sceneId+routingHeaderCacheKey,routingHeaders, cachetimeout, TimeUnit.MINUTES);

        redisUtils.set(sceneId+routingsupportingCacheKey,routingsupportings);
        GlobalCacheUtil.put(sceneId+routingsupportingCacheKey,routingsupportings, cachetimeout, TimeUnit.MINUTES);

        redisUtils.set(sceneId+routingSupportingReplaceCacheKey,replaces);
        GlobalCacheUtil.put(sceneId+routingSupportingReplaceCacheKey,replaces, cachetimeout, TimeUnit.MINUTES);

        redisUtils.set(sceneId+materialsCacheKey,useMaterials);
        GlobalCacheUtil.put(sceneId+materialsCacheKey,useMaterials, cachetimeout, TimeUnit.MINUTES);


    }
    private void  SaveDetailCache(String sceneId,List<RoutingDetail> RoutingDetails,List<RoutingDetailEquip> routingDetailEquips,List<RoutingDetailConnect> connections,List<RoutingDiscreteParam> routingDiscreteParams)
    {

        redisUtils.set(sceneId+routingDetailCacheKey,RoutingDetails);
        GlobalCacheUtil.put(sceneId+routingDetailCacheKey,RoutingDetails, cachetimeout, TimeUnit.MINUTES);

        redisUtils.set(sceneId+routingDetailEquipCacheKey,routingDetailEquips);
        GlobalCacheUtil.put(sceneId+routingDetailEquipCacheKey,routingDetailEquips, cachetimeout, TimeUnit.MINUTES);

        redisUtils.set(sceneId+routingDetailConnectCacheKey,connections);
        GlobalCacheUtil.put(sceneId+routingDetailConnectCacheKey,connections, cachetimeout, TimeUnit.MINUTES);

        redisUtils.set(sceneId+routingDiscreteParamCacheKey,routingDiscreteParams);
        GlobalCacheUtil.put(sceneId+routingDiscreteParamCacheKey,routingDiscreteParams, cachetimeout, TimeUnit.MINUTES);


    }

    private List<RoutingHeader>  GetRoutingHeader(String sceneId) {
        List<RoutingHeader> RoutingHeaders=(List<RoutingHeader>)GlobalCacheUtil.get(sceneId+routingHeaderCacheKey);
        if(RoutingHeaders==null)
        {
            RoutingHeaders=(List<RoutingHeader>)redisUtils.get(sceneId+routingHeaderCacheKey);
            if(RoutingHeaders!=null)
            {
                GlobalCacheUtil.put(sceneId+routingHeaderCacheKey,RoutingHeaders, cachetimeout, TimeUnit.MINUTES);
            }
        }
        return RoutingHeaders;
    }
    private List<Routingsupporting>  GetRoutingsupportings(String sceneId) {
        List<Routingsupporting> Routingsupportings=(List<Routingsupporting>)GlobalCacheUtil.get(sceneId+routingsupportingCacheKey);
        if(Routingsupportings==null)
        {
            Routingsupportings=(List<Routingsupporting>)redisUtils.get(sceneId+routingsupportingCacheKey);
            if(Routingsupportings!=null)
            {
                GlobalCacheUtil.put(sceneId+routingsupportingCacheKey,Routingsupportings, cachetimeout, TimeUnit.MINUTES);
            }
        }
        return Routingsupportings;
    }
    private List<RoutingSupportingReplace>  GetRoutingSupportingReplaces(String sceneId) {
        List<RoutingSupportingReplace> RoutingSupportingReplaces=(List<RoutingSupportingReplace>)GlobalCacheUtil.get(sceneId+routingSupportingReplaceCacheKey);
        if(RoutingSupportingReplaces==null)
        {
            RoutingSupportingReplaces=(List<RoutingSupportingReplace>)redisUtils.get(sceneId+routingSupportingReplaceCacheKey);
            if(RoutingSupportingReplaces!=null)
            {
                GlobalCacheUtil.put(sceneId+routingSupportingReplaceCacheKey,RoutingSupportingReplaces, cachetimeout, TimeUnit.MINUTES);
            }
        }
        return RoutingSupportingReplaces;
    }

    private List<RoutingHeader> getRoutingHeadersByIds(List<Integer> routingIds) {
        if (CollectionUtils.isEmpty(routingIds)) {
            return new ArrayList<>();
        }

        List<RoutingHeader> routingHeaders = new ArrayList<>();
        for (List<Integer> batchIds : partitionList(routingIds, ORACLE_IN_BATCH_SIZE)) {
            LambdaQueryWrapper<RoutingHeader> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(RoutingHeader::getId, batchIds);
            routingHeaders.addAll(routingHeaderMapper.selectList(wrapper));
        }
        return routingHeaders;
    }

    private List<Routingsupporting> getRoutingsupportingsByRoutingHeaderIds(List<? extends Number> routingIds) {
        if (CollectionUtils.isEmpty(routingIds)) {
            return new ArrayList<>();
        }

        List<Routingsupporting> routingsupportings = new ArrayList<>();
        for (List<? extends Number> batchIds : partitionList(routingIds, ORACLE_IN_BATCH_SIZE)) {
            LambdaQueryWrapper<Routingsupporting> routingsupportingwrapper = new LambdaQueryWrapper<>();
            routingsupportingwrapper.in(Routingsupporting::getRoutingHeaderId, batchIds)
                    .eq(Routingsupporting::getIsdeleted, 0);
            routingsupportings.addAll(routingsupportingMapper.selectList(routingsupportingwrapper));
        }
        return routingsupportings;
    }

    private List<RoutingSupportingReplace> getRoutingSupportingReplacesByStrsupids(List<String> routingSupportingIds) {
        if (CollectionUtils.isEmpty(routingSupportingIds)) {
            return new ArrayList<>();
        }

        List<RoutingSupportingReplace> replaces = new ArrayList<>();
        for (List<String> batchIds : partitionList(routingSupportingIds, ORACLE_IN_BATCH_SIZE)) {
            LambdaQueryWrapper<RoutingSupportingReplace> routingsupportingreplacewrapper = new LambdaQueryWrapper<>();
            routingsupportingreplacewrapper.in(RoutingSupportingReplace::getStrsupid, batchIds)
                    .eq(RoutingSupportingReplace::getIsdeleted, 0);
            replaces.addAll(routingSupportingReplaceMapper.selectList(routingsupportingreplacewrapper));
        }
        return replaces;
    }

    private <T> List<List<T>> partitionList(List<T> source, int batchSize) {
        List<List<T>> partitions = new ArrayList<>();
        if (CollectionUtils.isEmpty(source) || batchSize <= 0) {
            return partitions;
        }

        for (int i = 0; i < source.size(); i += batchSize) {
            partitions.add(source.subList(i, Math.min(i + batchSize, source.size())));
        }
        return partitions;
    }

    private List<RoutingDetail>  GetRoutingDetails(String sceneId) {
        List<RoutingDetail> RoutingDetails=(List<RoutingDetail>)GlobalCacheUtil.get(sceneId+routingDetailCacheKey);
        if(RoutingDetails==null)
        {
            RoutingDetails=(List<RoutingDetail>)redisUtils.get(sceneId+routingDetailCacheKey);
            if(RoutingDetails!=null)
            {
                GlobalCacheUtil.put(sceneId+routingDetailCacheKey,RoutingDetails, cachetimeout, TimeUnit.MINUTES);
            }
        }
        return RoutingDetails;
    }

    private List<RoutingDetailEquip>  GetRoutingDetailEquips(String sceneId) {
        List<RoutingDetailEquip> RoutingDetailEquips=(List<RoutingDetailEquip>)GlobalCacheUtil.get(sceneId+routingDetailEquipCacheKey);
        if(RoutingDetailEquips==null)
        {
            RoutingDetailEquips=(List<RoutingDetailEquip>)redisUtils.get(sceneId+routingDetailEquipCacheKey);
            if(RoutingDetailEquips!=null)
            {
                GlobalCacheUtil.put(sceneId+routingDetailEquipCacheKey,RoutingDetailEquips, cachetimeout, TimeUnit.MINUTES);
            }
        }
        return RoutingDetailEquips;
    }

    private List<RoutingDetailConnect>  GetRoutingDetailConnect(String sceneId) {
        List<RoutingDetailConnect> RoutingDetailConnects=(List<RoutingDetailConnect>)GlobalCacheUtil.get(sceneId+routingDetailConnectCacheKey);
        if(RoutingDetailConnects==null)
        {
            RoutingDetailConnects=(List<RoutingDetailConnect>)redisUtils.get(sceneId+routingDetailConnectCacheKey);
            if(RoutingDetailConnects!=null)
            {
                GlobalCacheUtil.put(sceneId+routingDetailConnectCacheKey,RoutingDetailConnects, cachetimeout, TimeUnit.MINUTES);
            }
        }
        return RoutingDetailConnects;
    }

    private List<RoutingDiscreteParam>  GetRoutingDiscreteParam(String sceneId) {
        List<RoutingDiscreteParam> RoutingDiscreteParams=(List<RoutingDiscreteParam>)GlobalCacheUtil.get(sceneId+routingDiscreteParamCacheKey);
        if(RoutingDiscreteParams==null)
        {
            RoutingDiscreteParams=(List<RoutingDiscreteParam>)redisUtils.get(sceneId+routingDiscreteParamCacheKey);
            if(RoutingDiscreteParams!=null)
            {
                GlobalCacheUtil.put(sceneId+routingDiscreteParamCacheKey,RoutingDiscreteParams, cachetimeout, TimeUnit.MINUTES);
            }
        }
        return RoutingDiscreteParams;
    }

    public TreeMap<String, Material>  GetMaterialListToMap(List<Material> materiallist)
    {
        if(materiallist==null) return null;
        TreeMap<String, Material> materials = materiallist.stream()
                .collect(Collectors.toMap(
                        // 1. Key映射：取Material.code
                        Material::getId,
                        // 2. Value映射：Material → Material
                        material -> material,
                        // 3. Key重复时的处理规则（保留旧值/覆盖新值）
                        (oldValue, newValue) -> newValue,
                        // 4. 指定返回TreeMap（有序）
                        TreeMap::new
                ));
        return materials;
    }

    public TreeMap<String, Material>  GetMaterials(String sceneId) {
        List<Material> materiallist=GetMaterialList(sceneId);
        if(materiallist==null) return null;

        return GetMaterialListToMap(materiallist);
    }

    public List<Material>  GetMaterialList(String sceneId) {
        List<Material> materials=(List<Material>)GlobalCacheUtil.get(sceneId+materialsCacheKey);
        if(materials==null)
        {
            materials=(List<Material>)redisUtils.get(sceneId+materialsCacheKey);
            if(materials!=null)
            {
                GlobalCacheUtil.put(sceneId+materialsCacheKey,materials, cachetimeout, TimeUnit.MINUTES);
            }
        }
        return materials;
    }
    public void  SetMaterials(String sceneId,List<Material> useMaterials) {
        redisUtils.set(sceneId + materialsCacheKey, useMaterials);
        GlobalCacheUtil.put(sceneId + materialsCacheKey, useMaterials, cachetimeout, TimeUnit.MINUTES);
    }

    private List<Equipinfo>  GetEquipinfos() {
        List<Equipinfo> equipinfoList=(List<Equipinfo>)GlobalCacheUtil.get("equipinfo");
        if(equipinfoList==null)
        {
            equipinfoList = equipinfoService.lambdaQuery().eq(Equipinfo::getIsdeleted, 0).list();

            GlobalCacheUtil.put("equipinfo",equipinfoList, cachetimeout, TimeUnit.MINUTES);

        }
        return equipinfoList;
    }

    private List<PlanResource>  GetPlanResources() {
        List<PlanResource> list=(List<PlanResource>) GlobalCacheUtil.get("PlanResource");
        if(list==null)
        {
            list = planResourceService.lambdaQuery()
                    .eq(PlanResource::getIsdeleted, 0)
                    .list();
            GlobalCacheUtil.put("PlanResource",list, cachetimeout, TimeUnit.MINUTES);

        }
        return list;
    }

    private List<Equiptype1>  GetEquipTypes() {
        List<Equiptype1> equipTypes=(List<Equiptype1>) GlobalCacheUtil.get("equipType");
        if(equipTypes==null)
        {
            equipTypes = equiptype1Service.lambdaQuery().eq(Equiptype1::getIsdeleted, 0).list();

            GlobalCacheUtil.put("equipType",equipTypes, cachetimeout, TimeUnit.MINUTES);

        }
        return equipTypes;
    }




    public void clearCache(String sceneId) {


        redisUtils.del(sceneId+routingHeaderCacheKey);
        GlobalCacheUtil.remove(sceneId+routingHeaderCacheKey);

        redisUtils.del(sceneId+routingsupportingCacheKey);
        GlobalCacheUtil.remove(sceneId+routingsupportingCacheKey);

        redisUtils.del(sceneId+routingSupportingReplaceCacheKey);
        GlobalCacheUtil.remove(sceneId+routingSupportingReplaceCacheKey);

        redisUtils.del(sceneId+routingDetailCacheKey);
        GlobalCacheUtil.remove(sceneId+routingDetailCacheKey);

        redisUtils.del(sceneId+routingDetailEquipCacheKey);
        GlobalCacheUtil.remove(sceneId+routingDetailEquipCacheKey);

        redisUtils.del(sceneId+routingDetailConnectCacheKey);
        GlobalCacheUtil.remove(sceneId+routingDetailConnectCacheKey);

        redisUtils.del(sceneId+routingDiscreteParamCacheKey);
        GlobalCacheUtil.remove(sceneId+routingDiscreteParamCacheKey);

        redisUtils.del(sceneId+materialsCacheKey);
        GlobalCacheUtil.remove(sceneId+materialsCacheKey);



    }
}
