package com.aps.service.Algorithm;

import com.aps.common.util.FileHelper;
import com.aps.common.util.GlobalCacheUtil;
import com.aps.common.util.ProductionDeepCopyUtil;
import com.aps.entity.Algorithm.*;
import com.aps.entity.Algorithm.IDAndChildID.GroupResult;
import com.aps.entity.basic.*;

import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

/**
 * 自适应大邻域搜索（ALNS）算法。
 *
 * <p>核心思想：
 * <ol>
 *   <li>多个 Destroy 算子（破坏解的一部分） + 多个 Repair 算子（修复被破坏的解）</li>
 *   <li>自适应权重：根据算子表现动态调整选择概率</li>
 *   <li>模拟退火接受准则：以一定概率接受劣解，概率随迭代递减</li>
 * </ol>
 *
 * <p>与 VNS 的区别：
 * <ul>
 *   <li>VNS 系统性地切换邻域结构（换设备 → 工序前移 → 工序交换）</li>
 *   <li>ALNS 随机选择 destroy/repair 组合，按权重进行 roulette wheel 选择</li>
 * </ul>
 *
 * <p>架构：
 * <pre>
 *   ALNS.search(chromosome, tabuSearch, vns, decoder, machines)
 *       │
 *       ├─ 每个迭代：
 *       │   ├─ roulette select destroy operator
 *       │   ├─ roulette select repair operator
 *       │   ├─ destroy(chromosome) → partial solution
 *       │   ├─ repair(partial solution) → candidate
 *       │   ├─ tabu check
 *       │   ├─ localSearch(candidate)
 *       │   ├─ SA acceptance
 *       │   └─ update operator weights
 *       │
 *       └─ return best
 * </pre>
 *
 * 作者：佟礼
 */
public class AdaptiveLargeNeighborhoodSearch {

    // ==================== 随机数 ====================
    private final Random rnd = new Random();

    // ==================== ALNS 核心参数 ====================
    private static final int MAX_ITERATIONS = 120;                    // 最大迭代次数
    private static final int MAX_NO_IMPROVE_ITERATIONS = 25;          // 最大连续无改进迭代
    private static final int SEGMENT_SIZE = 10;                       // 权重更新段大小（每 SEGMENT_SIZE 迭代更新一次权重）
    private static final double DESTROY_RATIO_MIN = 0.10;             // 最小破坏比例（提高以增强探索）
    private static final double DESTROY_RATIO_MAX = 0.40;             // 最大破坏比例
    private static final int MAX_RETRY_ATTEMPTS = 2;                  // 最多重试次数（首次失败后换组合）

    // ==================== 自适应权重参数 ====================
    private static final double INITIAL_WEIGHT = 1.0;                 // 初始权重
    private static final double REACTION_FACTOR = 0.7;                // 反应因子（历史权重与新分的比例）
    private static final double MIN_WEIGHT = 0.1;                     // 最小权重（防止算子完全熄灭）

    // ==================== 分数增量（越大越好） ====================
    private static final double SCORE_NEW_BEST = 3.0;                 // 发现新的全局最优解
    private static final double SCORE_BETTER = 1.5;                   // 比当前解更好
    private static final double SCORE_ACCEPTED = 0.8;                 // 劣解被接受
    private static final double SCORE_REJECTED = 0.1;                 // 劣解被拒绝

    // ==================== 模拟退火参数 ====================
    private static final double INITIAL_TEMPERATURE = 0.5;            // 初始温度
    private static final double COOLING_RATE = 0.98;                  // 冷却速率（加快冷却，使后期更聚焦）
    private static final double FINAL_TEMPERATURE = 0.01;             // 最终温度

    // ==================== 改进判断参数 ====================
    private static final double SIGNIFICANT_IMPROVEMENT_THRESHOLD = 1e-11;
    private static final double MINOR_IMPROVEMENT_THRESHOLD = 0.0;

    // ==================== 多轮修复参数 ====================
    private static final int MULTI_PASS_COUNT = 3;                    // 多轮修复尝试次数

    // ==================== 时间预算 ====================
    private static final long ALNS_TIME_BUDGET_MS = 15L * 60L * 1000L;
    private static final long ALNS_PER_ITER_BUDGET_MS = 17L * 1000L;

    // ==================== 依赖项 ====================
    private final List<Entry> allOperations;
    private final FitnessCalculator fitnessCalculator;
    private final List<Order> orders;
    private final TreeMap<String, Material> materials;
    private final List<GroupResult> entryRel;

    private final Map<Integer, Entry> entryByIds;

    // ==================== 缓存解码数据 ====================
    private List<Machine> cachedMachines;
    private List<Order> cachedOrders;
    private List<GroupResult> cachedEntryRel;
    private TreeMap<String, Material> cachedMaterials;
    private List<Entry> cachedAllOperations;

    // ==================== 算子注册表 ====================
    private final List<DestroyOperator> destroyOperators = new ArrayList<>();
    private final List<RepairOperator> repairOperators = new ArrayList<>();
    private double[] destroyWeights;
    private double[] destroyScores;
    private int[] destroyUseCount;
    private double[] repairWeights;
    private double[] repairScores;
    private int[] repairUseCount;

    // ==================== 构造函数 ====================

    public AdaptiveLargeNeighborhoodSearch(List<Entry> allOperations, List<Order> orders,
                                           TreeMap<String, Material> materials,
                                           List<GroupResult> entryRel,
                                           FitnessCalculator fitnessCalculator) {
        this.allOperations = allOperations;
        this.fitnessCalculator = fitnessCalculator;
        this.orders = orders;
        this.materials = materials;
        this.entryRel = entryRel;

        Map<Integer, Object> mp = buildEntryKey();

        this.entryByIds = (Map<Integer, Entry>) mp.get(1);

        // 预缓存解码数据
        this.cachedAllOperations = ProductionDeepCopyUtil.deepCopyList(
                new CopyOnWriteArrayList<>(allOperations), Entry.class);
        this.cachedOrders = ProductionDeepCopyUtil.deepCopyList(
                new CopyOnWriteArrayList<>(orders), Order.class);
        this.cachedEntryRel = ProductionDeepCopyUtil.deepCopyList(
                new CopyOnWriteArrayList<>(entryRel), GroupResult.class);
        this.cachedMaterials = ProductionDeepCopyUtil.deepCopyTreeMap(
                materials, String.class, Material.class);

        // 注册 destroy 算子
        registerDestroyOperators();
        // 注册 repair 算子
        registerRepairOperators();
        // 初始化权重
        initWeights();
    }

    // ==================== 算子注册 ====================

    private void registerDestroyOperators() {
        // 1. 随机换设备：随机选择部分工序更换机器
        destroyOperators.add(new DestroyOperator("RandomMachineChange", this::destroyRandomMachineChange));
        // 2. 瓶颈工序移除：移除瓶颈设备上的工序
        destroyOperators.add(new DestroyOperator("BottleneckOpRemoval", this::destroyBottleneckOps));
        // 3. 延迟工序打乱：打乱导致延迟的工序
        destroyOperators.add(new DestroyOperator("DelayOpShuffle", this::destroyDelayOps));
        // 4. 随机区间打乱：随机打乱一段连续的工序序列
        destroyOperators.add(new DestroyOperator("RandomSegmentShuffle", this::destroyRandomSegment));
        // 5. 负载均衡迁移：将超载机器上的工序迁移到低负载机器
        destroyOperators.add(new DestroyOperator("LoadBalanceTransfer", this::destroyLoadBalanceTransfer));
    }

    private void registerRepairOperators() {
        // 1. 多轮修复：多次调用 VNS 邻域生成，选最优结果
        repairOperators.add(new RepairOperator("MultiPassRepair", this::repairMultiPass));
        // 2. 贪婪换设备：对打乱的工序重新选择最优机器
        repairOperators.add(new RepairOperator("GreedyMachineReassign", this::repairGreedyMachine));
        // 3. 局部搜索修复：解码后通过 VNS 生成邻域
        repairOperators.add(new RepairOperator("LocalSearchRepair", this::repairLocalSearch));
    }

    private void initWeights() {
        destroyWeights = new double[destroyOperators.size()];
        destroyScores = new double[destroyOperators.size()];
        destroyUseCount = new int[destroyOperators.size()];
        Arrays.fill(destroyWeights, INITIAL_WEIGHT);

        repairWeights = new double[repairOperators.size()];
        repairScores = new double[repairOperators.size()];
        repairUseCount = new int[repairOperators.size()];
        Arrays.fill(repairWeights, INITIAL_WEIGHT);
    }

    // ====================================================================
    // 搜索主循环
    // ====================================================================

    /**
     * ALNS 搜索主循环。
     *
     * @param chromosome 初始解
     * @param tabuSearch 禁忌表（多算法共享）
     * @param vns        提供邻域生成与局部搜索
     * @param decoder    解码器
     * @param machines   机器列表
     * @return 优化后的最优解
     */
    public Chromosome search(Chromosome chromosome, TabuSearch tabuSearch,
                             VariableNeighborhoodSearch vns,
                             GeneticDecoder decoder, List<Machine> machines) {
        FileHelper.writeLogFile("ALNS - 开始执行");

        Chromosome current = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
        Chromosome best = ProductionDeepCopyUtil.deepCopy(chromosome, Chromosome.class);
        double currentBestFitness = best.getFitness();

        int iterations = 0;
        int improveCount = 0;
        int noImprovementCount = 0;
        double temperature = INITIAL_TEMPERATURE;

        // 时间预算
        long startTimeMs = System.currentTimeMillis();
        long remainingBudgetMs = Math.max(5L * 60L * 1000L, ALNS_TIME_BUDGET_MS / 2);
        int timeBasedMaxIter = (int) Math.max(20, remainingBudgetMs / ALNS_PER_ITER_BUDGET_MS);
        int maxIterations = Math.min(MAX_ITERATIONS, Math.max(40, timeBasedMaxIter));

        FileHelper.writeLogFile(String.format(
                "ALNS - 参数: 最大迭代=%d, 初始温度=%.3f, 冷却率=%.3f, 破坏比例=%.0f%%-%.0f%%, 时间预算=%.1fmin",
                maxIterations, INITIAL_TEMPERATURE, COOLING_RATE,
                DESTROY_RATIO_MIN * 100, DESTROY_RATIO_MAX * 100,
                (double) remainingBudgetMs / 60000.0));

        for (int iter = 0; iter < maxIterations; iter++) {
            iterations++;
            decoder.DelOrder(current);

            // ---- 1. 自适应选择 destroy + repair 算子 ----
            int destroyIdx = rouletteSelect(destroyWeights);
            int repairIdx = rouletteSelect(repairWeights);
            DestroyOperator destroyOp = destroyOperators.get(destroyIdx);
            RepairOperator repairOp = repairOperators.get(repairIdx);

            Chromosome repaired = null;
            int repairAttempt = 0;

            // ---- 重试机制：最多尝试 MAX_RETRY_ATTEMPTS 次不同的 destroy+repair 组合 ----
            for (; repairAttempt < MAX_RETRY_ATTEMPTS; repairAttempt++) {
                // ---- 2. Destroy：破坏当前解 ----
                Chromosome destroyed = destroyOp.apply(current, DESTROY_RATIO_MIN, DESTROY_RATIO_MAX);
                if (destroyed == null) {
                    // 换其他 destroy 算子重试
                    int newDestroyIdx = (destroyIdx + 1 + rnd.nextInt(destroyOperators.size() - 1)) % destroyOperators.size();
                    destroyIdx = newDestroyIdx;
                    destroyOp = destroyOperators.get(destroyIdx);
                    continue;
                }

                // ---- 3. Repair：修复被破坏的解 ----
                repaired = repairOp.apply(destroyed, vns, decoder, machines);
                if (repaired != null) {
                    break; // 修复成功，退出重试
                }
                // 修复失败，换算子重试
                int newRepairIdx = (repairIdx + 1 + rnd.nextInt(repairOperators.size() - 1)) % repairOperators.size();
                repairIdx = newRepairIdx;
                repairOp = repairOperators.get(repairIdx);
            }

            if (repaired == null) {
                noImprovementCount++;
                updateOperatorScores(destroyIdx, repairIdx, SCORE_REJECTED, false);
                continue;
            }

            // ---- 4. 禁忌检查 ----
            boolean tabuHit = tabuSearch.isChromosomeTabu(repaired);

            // ---- 5. 解码 ----
            decode(decoder, repaired, machines);
            tabuSearch.addChromosomeToTabu(repaired);

            // ---- 6. 接受准则 ----
            boolean betterThanBest = isBetter(repaired, best);
            boolean betterThanCurrent = isBetter(repaired, current);

            boolean accept;
            double score;

            if (betterThanBest) {
                // 渴望准则：无条件接受
                accept = true;
                score = SCORE_NEW_BEST;
            } else if (betterThanCurrent) {
                accept = true;
                score = SCORE_BETTER;
            } else if (!tabuHit) {
                // 模拟退火：接受劣解
                double delta = current.getFitness() - repaired.getFitness(); // 负值表示更差
                double acceptProb = Math.exp(delta / temperature);
                accept = rnd.nextDouble() < acceptProb;
                score = accept ? SCORE_ACCEPTED : SCORE_REJECTED;
            } else {
                accept = false;
                score = SCORE_REJECTED;
            }

            updateOperatorScores(destroyIdx, repairIdx, score, true);

            if (accept) {
                current = lightCopy(repaired);
                if (betterThanBest) {
                    best = lightCopy(repaired);
                    improveCount++;
                    double delta = best.getFitness() - currentBestFitness;
                    if (delta > MINOR_IMPROVEMENT_THRESHOLD) {
                        noImprovementCount = 0;
                        currentBestFitness = best.getFitness();
                        if (delta > SIGNIFICANT_IMPROVEMENT_THRESHOLD) {
                            FileHelper.writeLogFile(String.format(
                                    "ALNS - 找到更好解(显著), 迭代=%d, fitness=%.12f, destroy=%s, repair=%s",
                                    iterations, best.getFitness(), destroyOp.name, repairOp.name));
                        } else {
                            FileHelper.writeLogFile(String.format(
                                    "ALNS - 找到更好解(微小), 迭代=%d, fitness=%.12f, delta=%.2e, destroy=%s, repair=%s",
                                    iterations, best.getFitness(), delta, destroyOp.name, repairOp.name));
                        }
                    }
                }
            } else {
                noImprovementCount++;
            }

            // ---- 7. 温度冷却 ----
            temperature *= COOLING_RATE;
            if (temperature < FINAL_TEMPERATURE) {
                temperature = FINAL_TEMPERATURE;
            }

            // ---- 8. 段更新权重 ----
            if ((iter + 1) % SEGMENT_SIZE == 0) {
                updateWeights();
            }

            // ---- 9. 提前停止 ----
            if (noImprovementCount >= MAX_NO_IMPROVE_ITERATIONS) {
                FileHelper.writeLogFile(String.format(
                        "ALNS - 提前停止: 连续%d次无改进", MAX_NO_IMPROVE_ITERATIONS));
                break;
            }
            long elapsedMs = System.currentTimeMillis() - startTimeMs;
            if (elapsedMs > remainingBudgetMs) {
                FileHelper.writeLogFile(String.format(
                        "ALNS - 提前停止: 达到时间预算(%.1fmin)", elapsedMs / 60000.0));
                break;
            }

            // 每 10 次迭代输出一次状态
            if ((iter + 1) % 10 == 0) {
                FileHelper.writeLogFile(String.format(
                        "ALNS - 迭代%d/%d, 改进=%d, 无改进连续=%d, T=%.4f, fitness=%.12f",
                        iterations, maxIterations, improveCount, noImprovementCount,
                        temperature, best.getFitness()));
            }
        }

        // 最终权重更新
        updateWeights();

        FileHelper.writeLogFile(String.format(
                "ALNS - 结束: 总迭代=%d, 改进次数=%d, 最终fitness=%.12f, 最终温度=%.4f",
                iterations, improveCount, best.getFitness(), temperature));
        FileHelper.writeLogFile(KpiLowerBoundCalculator.generateGapReport(best));
        logOperatorStats();
        return best;
    }
    /**
     * 轻量拷贝：只复制 generateNeighbor/DelOrder 需要的字段，避免全量 JSON 深拷贝导致 OOM。
     * result/machines/operatRel 等重型数据共享引用（generateNeighbor 只读，不修改）。
     */
    private Chromosome lightCopy(Chromosome source) {
        Chromosome copy = new Chromosome();
        copy.setOperationSequencing(new CopyOnWriteArrayList<>(source.getOperationSequencing()));
        copy.setMachineSelection(new CopyOnWriteArrayList<>(source.getMachineSelection()));
        copy.setGlobalOpList(new CopyOnWriteArrayList<>(source.getGlobalOpList()));
        copy.setOrders(new CopyOnWriteArrayList<>(source.getOrders()));
        copy.setAllOperations(new CopyOnWriteArrayList<>(source.getAllOperations()));
        copy.setResult(source.getResult());
        copy.setMachines(source.getMachines());
        copy.setOperatRel(new CopyOnWriteArrayList<>(source.getOperatRel()));
        copy.setScenarioID(source.getScenarioID());
        copy.setBaseTime(source.getBaseTime());
        copy.setGenerateType(source.getGenerateType());
        copy.setFitnessLevel(source.getFitnessLevel());
        copy.setFitness(source.getFitness());

        return copy;
    }
    // ====================================================================
    // Destroy 算子（破坏部分解）
    // ====================================================================

    /**
     * Destroy 1: 随机换设备。
     * 随机选择 destroyRatio 比例的工序，为其更换机器（如果有多个机器选项）。
     */
    private Chromosome destroyRandomMachineChange(Chromosome c, double destroyRatioMin, double destroyRatioMax) {
        List<GAScheduleResult> results = c.getResult();
        if (results == null || results.isEmpty()) return c;

        // 只选择有多个机器选项的工序
        List<GAScheduleResult> candidates = results.stream()
                .filter(r -> {
                    Entry e = entryByIds.get(r.getOperationId());
                    return e != null && e.getMachineOptions() != null && e.getMachineOptions().size() > 1;
                })
                .collect(Collectors.toList());
        if (candidates.isEmpty()) return c;

        double ratio = destroyRatioMin + rnd.nextDouble() * (destroyRatioMax - destroyRatioMin);
        int destroyCount = Math.max(1, (int) (candidates.size() * ratio));
        Collections.shuffle(candidates, rnd);

        Chromosome copy = copyChromosome(c);
        CopyOnWriteArrayList<Integer> machineSel = copy.getMachineSelection();
        if (machineSel == null) return copy;

        // 构建正确的 machineSelection 位置索引：groupId_sequence → globalOpList 索引
        Map<String, Integer> machinePosIndex = new HashMap<>();
        List<GlobalOperationInfo> globalOpList = c.getGlobalOpList();
        for (int i = 0; i < globalOpList.size(); i++) {
            Entry op = globalOpList.get(i).getOp();
            machinePosIndex.put(op.getGroupId() + "_" + op.getSequence(), i);
        }

        for (int i = 0; i < Math.min(destroyCount, candidates.size()); i++) {
            GAScheduleResult sr = candidates.get(i);
            Entry entry = entryByIds.get(sr.getOperationId());
            if (entry == null || entry.getMachineOptions() == null) continue;
            List<MachineOption> options = entry.getMachineOptions();
            if (options.size() <= 1) continue;
            String key = entry.getGroupId() + "_" + entry.getSequence();
            Integer pos = machinePosIndex.get(key);
            if (pos == null || pos >= machineSel.size()) continue;
            // 随机选一个不同的机器（machineSelection 存的是 1-based 序号，不是 machineId）
            int currentIdx = machineSel.get(pos) - 1; // 转为 0-based
            int newIdx;
            if (options.size() == 2) {
                newIdx = (currentIdx == 0) ? 1 : 0;
            } else {
                do {
                    newIdx = rnd.nextInt(options.size());
                } while (newIdx == currentIdx);
            }
            machineSel.set(pos, newIdx + 1);
        }
        return copy;
    }

    /**
     * Destroy 2: 瓶颈工序移除。
     * 找到瓶颈设备上的工序，打乱它们在 operationSequencing 中的位置。
     */
    private Chromosome destroyBottleneckOps(Chromosome c, double destroyRatioMin, double destroyRatioMax) {
        List<GAScheduleResult> results = c.getResult();
        if (results == null || results.isEmpty()) return c;

        // 简单瓶颈识别：利用率最高的机器
        Map<Long, Double> utilMap = new HashMap<>();
        Map<Long, Long> timeMap = new HashMap<>();
        for (GAScheduleResult r : results) {
            Long mid = r.getMachineId();
            utilMap.merge(mid, r.getProcessingTime(), Double::sum);
            timeMap.merge(mid, (long) (r.getEndTime() - r.getStartTime()), Long::sum);
        }
        Long bottleneckMachineId = utilMap.entrySet().stream()
                .max(Map.Entry.comparingByValue())
                .map(Map.Entry::getKey)
                .orElse(null);
        if (bottleneckMachineId == null) return c;

        List<GAScheduleResult> bottleneckOps = results.stream()
                .filter(r -> bottleneckMachineId.equals(r.getMachineId()))
                .collect(Collectors.toList());
        if (bottleneckOps.size() < 2) return c;

        double ratio = destroyRatioMin + rnd.nextDouble() * (destroyRatioMax - destroyRatioMin);
        int destroyCount = Math.max(2, (int) (bottleneckOps.size() * ratio));

        Chromosome copy = copyChromosome(c);
        CopyOnWriteArrayList<Integer> opSeq = copy.getOperationSequencing();
        if (opSeq == null) return copy;

        // 找到瓶颈工序在 opSeq 中的位置
        Set<Integer> bottleneckEntryIds = bottleneckOps.stream()
                .map(GAScheduleResult::getOperationId)
                .collect(Collectors.toSet());
        List<Integer> bottleneckPositions = new ArrayList<>();
        for (int i = 0; i < opSeq.size(); i++) {
            if (bottleneckEntryIds.contains(opSeq.get(i))) {
                bottleneckPositions.add(i);
            }
        }
        if (bottleneckPositions.size() < 2) return copy;

        // 随机选择 destroyCount 个位置，打乱它们的值
        Collections.shuffle(bottleneckPositions, rnd);
        List<Integer> selectedPositions = bottleneckPositions.subList(0,
                Math.min(destroyCount, bottleneckPositions.size()));
        List<Integer> values = new ArrayList<>();
        for (int pos : selectedPositions) {
            values.add(opSeq.get(pos));
        }
        Collections.shuffle(values, rnd);
        for (int j = 0; j < selectedPositions.size(); j++) {
            opSeq.set(selectedPositions.get(j), values.get(j));
        }
        return copy;
    }

    /**
     * Destroy 3: 延迟工序打乱。
     * 找到导致延迟的工序，打乱它们的机器选择。
     */
    private Chromosome destroyDelayOps(Chromosome c, double destroyRatioMin, double destroyRatioMax) {
        List<Order> orderList = c.getOrders();
        if (orderList == null || orderList.isEmpty()) return c;

        // 找到延迟的订单
        Set<String> delayedOrderIds = orderList.stream()
                .filter(o -> o.getDelayHours() > 0)
                .map(Order::getOrderId)
                .collect(Collectors.toSet());
        if (delayedOrderIds.isEmpty()) return c;

        List<GAScheduleResult> results = c.getResult();
        if (results == null || results.isEmpty()) return c;

        List<GAScheduleResult> delayedResults = results.stream()
                .filter(r -> delayedOrderIds.contains(r.getOrderId()))
                .collect(Collectors.toList());
        if (delayedResults.isEmpty()) return c;

        double ratio = destroyRatioMin + rnd.nextDouble() * (destroyRatioMax - destroyRatioMin);
        int destroyCount = Math.max(1, (int) (delayedResults.size() * ratio));
        Collections.shuffle(delayedResults, rnd);

        Chromosome copy = copyChromosome(c);
        CopyOnWriteArrayList<Integer> machineSel = copy.getMachineSelection();
        if (machineSel == null) return copy;

        // 构建正确的 machineSelection 位置索引：groupId_sequence → globalOpList 索引
        Map<String, Integer> machinePosIndex = new HashMap<>();
        List<GlobalOperationInfo> globalOpList = c.getGlobalOpList();
        for (int i = 0; i < globalOpList.size(); i++) {
            Entry op = globalOpList.get(i).getOp();
            machinePosIndex.put(op.getGroupId() + "_" + op.getSequence(), i);
        }

        for (int i = 0; i < Math.min(destroyCount, delayedResults.size()); i++) {
            GAScheduleResult sr = delayedResults.get(i);
            Entry entry = entryByIds.get(sr.getOperationId());
            if (entry == null || entry.getMachineOptions() == null || entry.getMachineOptions().isEmpty())
                continue;
            List<MachineOption> options = entry.getMachineOptions();
            if (options.size() <= 1) continue;
            String key = entry.getGroupId() + "_" + entry.getSequence();
            Integer pos = machinePosIndex.get(key);
            if (pos == null || pos >= machineSel.size()) continue;
            // 随机选一个不同的机器（machineSelection 存的是 1-based 序号，不是 machineId）
            int currentIdx = machineSel.get(pos) - 1;
            int newIdx;
            if (options.size() == 2) {
                newIdx = (currentIdx == 0) ? 1 : 0;
            } else {
                do {
                    newIdx = rnd.nextInt(options.size());
                } while (newIdx == currentIdx);
            }
            machineSel.set(pos, newIdx + 1);
        }
        return copy;
    }

    /**
     * Destroy 4: 随机区间打乱。
     * 在 operationSequencing 中随机选一段连续区间，打乱其内部顺序。
     */
    private Chromosome destroyRandomSegment(Chromosome c, double destroyRatioMin, double destroyRatioMax) {
        CopyOnWriteArrayList<Integer> opSeq = c.getOperationSequencing();
        if (opSeq == null || opSeq.size() < 4) return c;

        Chromosome copy = copyChromosome(c);
        CopyOnWriteArrayList<Integer> seq = copy.getOperationSequencing();
        if (seq == null) return copy;

        double ratio = destroyRatioMin + rnd.nextDouble() * (destroyRatioMax - destroyRatioMin);
        int segmentLen = Math.max(2, (int) (seq.size() * ratio));
        int start = rnd.nextInt(Math.max(1, seq.size() - segmentLen));
        int end = Math.min(seq.size(), start + segmentLen);

        // 打乱 [start, end) 区间
        List<Integer> subList = new ArrayList<>(seq.subList(start, end));
        Collections.shuffle(subList, rnd);
        for (int i = start; i < end; i++) {
            seq.set(i, subList.get(i - start));
        }
        return copy;
    }

    /**
     * Destroy 5: 负载均衡迁移。
     * 利用解码后的调度数据，找出利用率最高和最低的机器，
     * 将超载机器上有多机器选项的工序迁移到低负载机器上。
     */
    private Chromosome destroyLoadBalanceTransfer(Chromosome c, double destroyRatioMin, double destroyRatioMax) {
        List<GAScheduleResult> results = c.getResult();
        if (results == null || results.isEmpty()) return c;

        // 构建每台机器的利用率数据
        Map<Long, MachineUtilInfo> machineUtilMap = buildMachineUtilization(results);
        if (machineUtilMap.size() < 2) return c;

        // 找出超载机器（利用率 > 70%）和低负载机器（利用率 < 40%）
        List<Long> overloadedMachines = new ArrayList<>();
        List<Long> underloadedMachines = new ArrayList<>();
        double totalSpan = 0;
        for (MachineUtilInfo info : machineUtilMap.values()) {
            totalSpan = Math.max(totalSpan, info.span);
        }
        for (Map.Entry<Long, MachineUtilInfo> entry : machineUtilMap.entrySet()) {
            double util = totalSpan > 0 ? entry.getValue().span / totalSpan * 100 : 0;
            if (util > 70) overloadedMachines.add(entry.getKey());
            if (util < 40) underloadedMachines.add(entry.getKey());
        }
        if (overloadedMachines.isEmpty() || underloadedMachines.isEmpty()) return c;

        // 收集超载机器上有多个机器选项的工序
        Set<Long> overloadedSet = new HashSet<>(overloadedMachines);
        List<GAScheduleResult> candidates = results.stream()
                .filter(r -> overloadedSet.contains(r.getMachineId()))
                .filter(r -> {
                    Entry e = entryByIds.get(r.getOperationId());
                    return e != null && e.getMachineOptions() != null && e.getMachineOptions().size() > 1;
                })
                .collect(Collectors.toList());
        if (candidates.isEmpty()) return c;

        double ratio = destroyRatioMin + rnd.nextDouble() * (destroyRatioMax - destroyRatioMin);
        int destroyCount = Math.max(1, (int) (candidates.size() * ratio));
        Collections.shuffle(candidates, rnd);

        Chromosome copy = copyChromosome(c);
        CopyOnWriteArrayList<Integer> machineSel = copy.getMachineSelection();
        if (machineSel == null) return copy;

        // 构建 machineSelection 位置索引
        Map<String, Integer> machinePosIndex = new HashMap<>();
        List<GlobalOperationInfo> globalOpList = c.getGlobalOpList();
        for (int i = 0; i < globalOpList.size(); i++) {
            Entry op = globalOpList.get(i).getOp();
            machinePosIndex.put(op.getGroupId() + "_" + op.getSequence(), i);
        }

        // 构建低负载机器可用的 machineId 集合
        Set<Long> underloadedMachineIds = new HashSet<>(underloadedMachines);

        int transferred = 0;
        for (int i = 0; i < Math.min(destroyCount, candidates.size()); i++) {
            GAScheduleResult sr = candidates.get(i);
            Entry entry = entryByIds.get(sr.getOperationId());
            if (entry == null || entry.getMachineOptions() == null) continue;
            List<MachineOption> options = entry.getMachineOptions();
            if (options.size() <= 1) continue;

            // 找到该工序可用的低负载机器选项
            List<Integer> lowLoadIndices = new ArrayList<>();
            for (int j = 0; j < options.size(); j++) {
                if (underloadedMachineIds.contains(options.get(j).getMachineId())) {
                    lowLoadIndices.add(j);
                }
            }
            if (lowLoadIndices.isEmpty()) continue;

            String key = entry.getGroupId() + "_" + entry.getSequence();
            Integer pos = machinePosIndex.get(key);
            if (pos == null || pos >= machineSel.size()) continue;

            // 随机选一个低负载机器
            int newIdx = lowLoadIndices.get(rnd.nextInt(lowLoadIndices.size()));
            machineSel.set(pos, newIdx + 1);
            transferred++;
        }

        if (transferred > 0) {
            FileHelper.writeLogFile(String.format(
                    "ALNS-负载均衡迁移: 超载机器=%d台, 低负载机器=%d台, 转移工序=%d/%d",
                    overloadedMachines.size(), underloadedMachines.size(), transferred, destroyCount));
        }
        return copy;
    }

    // ====================================================================
    // Repair 算子（修复被破坏的解）
    // ====================================================================

    /**
     * Repair 1: 多轮修复。
     * 多次调用 VNS 的 generateNeighbor，每次解码并比较，选最优结果。
     * 这比单次 generateNeighbor 更有可能找到改进。
     */
    private Chromosome repairMultiPass(Chromosome c, VariableNeighborhoodSearch vns,
                                       GeneticDecoder decoder, List<Machine> machines) {
        Chromosome base = copyChromosome(c);
        decode(decoder, base, machines);

        Chromosome bestRepair = base;
        double bestRepairFitness = base.getFitness();

        for (int pass = 0; pass < MULTI_PASS_COUNT; pass++) {
            // 基于当前最优修复结果生成邻域
            Chromosome neighbor = vns.generateNeighbor(bestRepair);
            if (neighbor == null) continue;

            // 解码邻域
            Chromosome neighborCopy = copyChromosome(neighbor);
            neighborCopy.setResult(new CopyOnWriteArrayList<>());
            decode(decoder, neighborCopy, machines);

            if (isBetter(neighborCopy, bestRepair)) {
                bestRepair = neighborCopy;
                bestRepairFitness = bestRepair.getFitness();
            }
        }
        return bestRepair;
    }

    /**
     * Repair 2: 贪婪换设备。
     * 通过 VNS 的 generateNeighbor 生成邻居后，再调用局部搜索修复。
     */
    private Chromosome repairGreedyMachine(Chromosome c, VariableNeighborhoodSearch vns,
                                           GeneticDecoder decoder, List<Machine> machines) {
        // 通过 VNS 的瓶颈感知策略生成一个邻居
        Chromosome neighbor = vns.generateNeighbor(c);
        if (neighbor == null) return c;
        return neighbor;
    }

    /**
     * Repair 3: 局部搜索修复。
     * 通过 VNS 的局部搜索对解进行修复优化。
     */
    private Chromosome repairLocalSearch(Chromosome c, VariableNeighborhoodSearch vns,
                                         GeneticDecoder decoder, List<Machine> machines) {
        // 深拷贝后解码，再通过 VNS 的 generateNeighbor 生成一个邻居
        Chromosome copy = copyChromosome(c);
        decode(decoder, copy, machines);
        Chromosome neighbor = vns.generateNeighbor(copy);
        return neighbor != null ? neighbor : copy;
    }

    // ====================================================================
    // 自适应权重管理
    // ====================================================================

    /**
     * 轮盘赌选择算子。
     */
    private int rouletteSelect(double[] weights) {
        double total = 0.0;
        for (double w : weights) total += w;
        if (total <= 0) return rnd.nextInt(weights.length);
        double rand = rnd.nextDouble() * total;
        double cumulative = 0.0;
        for (int i = 0; i < weights.length; i++) {
            cumulative += weights[i];
            if (rand <= cumulative) return i;
        }
        return weights.length - 1;
    }

    /**
     * 更新算子分数（累加到此段的 score 中）。
     */
    private void updateOperatorScores(int destroyIdx, int repairIdx, double score, boolean used) {
        destroyScores[destroyIdx] += score;
        repairScores[repairIdx] += score;
        if (used) {
            destroyUseCount[destroyIdx]++;
            repairUseCount[repairIdx]++;
        }
    }

    /**
     * 段结束时更新权重。
     * 权重 = reactionFactor * 旧权重 + (1 - reactionFactor) * (段分数 / 使用次数)
     */
    private void updateWeights() {
        for (int i = 0; i < destroyWeights.length; i++) {
            double avgScore = destroyUseCount[i] > 0
                    ? destroyScores[i] / destroyUseCount[i] : 0.0;
            destroyWeights[i] = Math.max(MIN_WEIGHT,
                    REACTION_FACTOR * destroyWeights[i] + (1 - REACTION_FACTOR) * avgScore);
            destroyScores[i] = 0.0;
            destroyUseCount[i] = 0;
        }
        for (int i = 0; i < repairWeights.length; i++) {
            double avgScore = repairUseCount[i] > 0
                    ? repairScores[i] / repairUseCount[i] : 0.0;
            repairWeights[i] = Math.max(MIN_WEIGHT,
                    REACTION_FACTOR * repairWeights[i] + (1 - REACTION_FACTOR) * avgScore);
            repairScores[i] = 0.0;
            repairUseCount[i] = 0;
        }
    }

    /**
     * 输出算子权重统计。
     */
    private void logOperatorStats() {
        StringBuilder sb = new StringBuilder("ALNS - 算子权重: ");
        sb.append("Destroy[");
        for (int i = 0; i < destroyOperators.size(); i++) {
            sb.append(String.format("%s=%.3f", destroyOperators.get(i).name, destroyWeights[i]));
            if (i < destroyOperators.size() - 1) sb.append(", ");
        }
        sb.append("] Repair[");
        for (int i = 0; i < repairOperators.size(); i++) {
            sb.append(String.format("%s=%.3f", repairOperators.get(i).name, repairWeights[i]));
            if (i < repairOperators.size() - 1) sb.append(", ");
        }
        sb.append("]");
        FileHelper.writeLogFile(sb.toString());
    }

    // ====================================================================
    // 辅助方法（复用 VNS 风格）
    // ====================================================================

    /**
     * 从调度结果构建每台机器的利用率数据。
     */
    private Map<Long, MachineUtilInfo> buildMachineUtilization(List<GAScheduleResult> results) {
        Map<Long, MachineUtilInfo> map = new HashMap<>();
        for (GAScheduleResult r : results) {
            Long mid = r.getMachineId();
            MachineUtilInfo info = map.get(mid);
            if (info == null) {
                info = new MachineUtilInfo();
                info.machineId = mid;
                info.minStart = r.getStartTime();
                info.maxEnd = r.getEndTime();
                info.opCount = 1;
                info.totalWork = r.getProcessingTime();
                map.put(mid, info);
            } else {
                info.minStart = Math.min(info.minStart, r.getStartTime());
                info.maxEnd = Math.max(info.maxEnd, r.getEndTime());
                info.opCount++;
                info.totalWork += r.getProcessingTime();
            }
        }
        // 计算每台机器的 span
        for (MachineUtilInfo info : map.values()) {
            info.span = info.maxEnd - info.minStart;
        }
        return map;
    }

    private void decode(GeneticDecoder decoder, Chromosome chromosome, List<Machine> machines) {
        chromosome.setResult(new CopyOnWriteArrayList<>());
        if (cachedMachines == null) {
            cachedMachines = ProductionDeepCopyUtil.deepCopyList(machines, Machine.class);
        }
        chromosome.setMachines(ProductionDeepCopyUtil.deepCopyList(cachedMachines, Machine.class));
        chromosome.setOrders(ProductionDeepCopyUtil.deepCopyList(
                new CopyOnWriteArrayList<>(cachedOrders), Order.class));
        chromosome.setOperatRel(ProductionDeepCopyUtil.deepCopyList(
                new CopyOnWriteArrayList<>(cachedEntryRel), GroupResult.class));
        chromosome.setMaterials(ProductionDeepCopyUtil.deepCopyTreeMap(
                cachedMaterials, String.class, Material.class));
        chromosome.setAllOperations(ProductionDeepCopyUtil.deepCopyList(
                new CopyOnWriteArrayList<>(cachedAllOperations), Entry.class));

        List<GAScheduleResult> lockedOrders = GlobalCacheUtil.get("locked_orders_" + chromosome.getScenarioID());
        if (lockedOrders != null && !lockedOrders.isEmpty()) {
            chromosome.setResultOld(ProductionDeepCopyUtil.deepCopyList(lockedOrders, GAScheduleResult.class));
        } else {
            chromosome.setResultOld(new CopyOnWriteArrayList<>());
        }
        decoder.decodeChromosomeWithCache(chromosome, false);
    }

    private Chromosome copyChromosome(Chromosome c) {
        Chromosome copy = new Chromosome();
        if (c.getMachineSelection() != null) {
            copy.setMachineSelection(new CopyOnWriteArrayList<>(c.getMachineSelection()));
        }
        if (c.getOperationSequencing() != null) {
            copy.setOperationSequencing(new CopyOnWriteArrayList<>(c.getOperationSequencing()));
        }
        if (c.getObjectives() != null) {
            copy.setObjectives(Arrays.copyOf(c.getObjectives(), c.getObjectives().length));
        }
        if (c.getGlobalOpList() != null) {
            copy.setGlobalOpList(new CopyOnWriteArrayList<>(c.getGlobalOpList()));
        }
        copy.setMachines(c.getMachines());
        copy.setOrders(c.getOrders());
        copy.setOperatRel(c.getOperatRel());
        copy.setMaterials(c.getMaterials());
        copy.setAllOperations(c.getAllOperations());
        copy.setFitness(c.getFitness());
        copy.setFitnessLevel(c.getFitnessLevel());
        copy.setResult(c.getResult());
        copy.setScenarioID(c.getScenarioID());
        copy.setBaseTime(c.getBaseTime());
        return copy;
    }

    private boolean isBetter(Chromosome c1, Chromosome c2) {
        return fitnessCalculator.isBetter(c1, c2);
    }

    private Map<Integer, Object> buildEntryKey() {
        Map<String, Entry> entryMap = new HashMap<>();
        Map<Integer, Entry> entryByIdMap = new HashMap<>();
        for (Entry entry : allOperations) {


                entryByIdMap.put(entry.getId(), entry);

        }
        Map<Integer, Object> result = new HashMap<>();

        result.put(1, entryByIdMap);
        return result;
    }

    // ====================================================================
    // 内部类
    // ====================================================================

    /**
     * 机器利用率信息（用于负载均衡计算）。
     */
    private static class MachineUtilInfo {
        long machineId;
        double minStart;
        double maxEnd;
        double span;
        int opCount;
        double totalWork;
    }

    /**
     * Destroy 算子：破坏解的一部分。
     */
    private static class DestroyOperator {
        final String name;
        final DestroyFunction function;

        DestroyOperator(String name, DestroyFunction function) {
            this.name = name;
            this.function = function;
        }

        Chromosome apply(Chromosome c, double ratioMin, double ratioMax) {
            try {
                return function.apply(c, ratioMin, ratioMax);
            } catch (Exception e) {
                FileHelper.writeLogFile("ALNS - Destroy算子 " + name + " 异常: " + e.getMessage());
                return null;
            }
        }
    }

    @FunctionalInterface
    private interface DestroyFunction {
        Chromosome apply(Chromosome c, double ratioMin, double ratioMax);
    }

    /**
     * Repair 算子：修复被破坏的解。
     */
    private static class RepairOperator {
        final String name;
        final RepairFunction function;

        RepairOperator(String name, RepairFunction function) {
            this.name = name;
            this.function = function;
        }

        Chromosome apply(Chromosome c, VariableNeighborhoodSearch vns,
                         GeneticDecoder decoder, List<Machine> machines) {
            try {
                return function.apply(c, vns, decoder, machines);
            } catch (Exception e) {
                FileHelper.writeLogFile("ALNS - Repair算子 " + name + " 异常: " + e.getMessage());
                return null;
            }
        }
    }

    @FunctionalInterface
    private interface RepairFunction {
        Chromosome apply(Chromosome c, VariableNeighborhoodSearch vns,
                         GeneticDecoder decoder, List<Machine> machines);
    }
}