package com.aps.service.Algorithm;

import com.aps.common.util.*;
import com.aps.entity.Algorithm.*;
import com.aps.entity.Algorithm.IDAndChildID.GroupResult;
import com.aps.entity.basic.*;
import com.aps.service.plan.MachineSchedulerService;
import com.aps.service.plan.SceneService;
import org.springframework.beans.factory.annotation.Autowired;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

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

public class GeneticAlgorithm {
    private final Random rnd = new Random();
    private  List<Machine> machines;
    private final MachineSchedulerService machineScheduler;
    private final List<Order> orders;
    private final TreeMap<String, Material> materials;

    private final List<String> materialIds;

    private static GlobalParam _GlobalParam;
    private  List<GroupResult> _entryRel;

    FitnessCalculator _fitnessCalculator = new FitnessCalculator();

    private NSGAIIUtils _nsgaIIUtils = new NSGAIIUtils();

    private ObjectiveWeights _objectiveWeights = new ObjectiveWeights();


    private MaterialRequirementService materialRequirementService;

    private List<OrderMaterialRequirement> orderMaterials;


    private SceneService _sceneService;

    private String sceneId;

    public GeneticAlgorithm(GlobalParam globalParam,List<Machine> machines, List<Order> orders,
                            TreeMap<String, Material> materials,List<String> _materialIds, MachineSchedulerService machineScheduler,List<GroupResult> entryRel,MaterialRequirementService _materialRequirementService,SceneService sceneService,String _sceneId) {
        this.machines = machines;
        this.orders = orders;
        this.materials = materials;
        this.machineScheduler = machineScheduler;
        _GlobalParam=globalParam;
        _entryRel=entryRel;
        materialRequirementService=_materialRequirementService;
        _sceneService=sceneService;
        sceneId=_sceneId;
        materialIds=_materialIds;
    }

    public void Init() {
        // 自定义权重配置

        _nsgaIIUtils.init(_GlobalParam);
    }

    public Chromosome Run(ScheduleParams param, List<Entry> allOperations) {

        if(allOperations==null||allOperations.size()==0)
        {
            throw new RuntimeException("没有待排产工单");
        }

        LocalDateTime starttime=LocalDateTime.now();
        FileHelper.writeLogFile("排产-----------开始-----------"+allOperations.get(0).getSceneId());

        Initialization initialization = new Initialization(_GlobalParam,allOperations,orders,machines,_objectiveWeights);

        GeneticOperations geneticOps = new GeneticOperations(_GlobalParam,allOperations,param);

        // 预生成全局工序列表（所有初始化方法共享同一顺序）
        List<GlobalOperationInfo> globalOpList = initialization.generateGlobalOpList();
        FileHelper.writeLogFile("初始化种群-----------开始-------");

        // 步骤1：初始化种群
        List<Chromosome> population = initialization.generateInitialPopulation(param, globalOpList);


        population= chromosomeDistinct(population);



        FileHelper.writeLogFile("初始化种群-----------结束-------");
        FileHelper.writeLogFile("初始化批量解码-----------开始-------");
        Chromosomedecode(param,allOperations,globalOpList,population);
        FileHelper.writeLogFile("初始化批量解码-----------结束-------");
        List<List<Chromosome>> combinedFronts = _nsgaIIUtils.parallelFastNonDominatedSort(population);
        int ordercount = globalOpList.stream()
                .mapToInt(GlobalOperationInfo::getGroupId)
                .max()
                .orElse(0);
        Chromosome best=GetBest(combinedFronts,"初始");

//        best=fronts.get(0).stream()
//                .max(Comparator.comparingDouble(Chromosome::getFitness))
//                .orElse(null);

        double bestFitness=best.getFitness();

        if(population.size()<param.getTournamentSize())
        {
            best.setBaseTime(param.getBaseTime());
            // best.setOrderMaterials(orderMaterials);
            best.setMaterialIds(materialIds);
            best.setMaterials(null);
            best.setScenarioID(sceneId);
            // best.setOperatRel(_entryRel);

            if(best.getInitMachines()==null)
            {
                best.setInitMachines(ProductionDeepCopyUtil.deepCopyList(machines,Machine.class));
            }
            LocalDateTime endtime1=LocalDateTime.now();
            FileHelper.writeLogFile(String.format("排产-------总方案数%d----结束---%s----耗时%d----",population.size(),allOperations.get(0).getSceneId(),DateTimeUtil.diffDuration(starttime,endtime1).getSeconds()) );
            return best;
        }


        int Iteration=0;
        // 步骤2：迭代进化
        FileHelper.writeLogFile("迭代进化-----------开始-------"+param.getMaxIterations());
        for (int iter = 0; iter < param.getMaxIterations(); iter++) {
            // 解码并计算适应度
            FileHelper.writeLogFile("迭代进化------"+iter+"-----开始-------");


            // 计算种群适应度标准差，微调参数
            double fitnessStd = _fitnessCalculator.calculateFitnessStd(population);
            param.fineTuneParams(iter, fitnessStd);


            // 检查终止条件（此处简化为迭代次数）
            if (iter == param.getMaxIterations() - 1) {
                break;
            }
            FileHelper.writeLogFile("选择操作-----------开始-------");

            // 选择前移除适应度为 0 或明显劣于当前最优解的个体，减少选择池规模：
            double minValidFitness = bestFitness * 0.5; // 保留最优解50%以上的个体
            List<Chromosome> validPopulation = population.stream()
                    .filter(c -> c.getFitness() >= minValidFitness)
                    .collect(Collectors.toList());

            // 选择操作
            List<Chromosome> selected = geneticOps.tournamentSelection(validPopulation);
            FileHelper.writeLogFile("选择操作-----------结束-------");
            // 交叉操作
            FileHelper.writeLogFile("交叉操作-----------开始-------");

            List<Chromosome> nextPopulation = new ArrayList<>();
            for (int i = 0; i < selected.size(); i += 2) {
                if (i + 1 >= selected.size()) {
                    selected.get(i).setID(UUID.randomUUID().toString());
                    nextPopulation.add(selected.get(i));
                    break;
                }

                Chromosome parent1 = selected.get(i);
                Chromosome parent2 = selected.get(i + 1);
                if (rnd.nextDouble() < param.getCrossoverProb()) {
                    // 假设PoxCrossover返回包含两个子染色体的数组
                    Pair<Chromosome, Chromosome> children = geneticOps.poxCrossover(parent1, parent2, ordercount);
                    nextPopulation.add(children.getFirst());
                    nextPopulation.add(children.getSecond());
                } else {
                    nextPopulation.add(parent1);
                    nextPopulation.add(parent2);
                }
            }
            FileHelper.writeLogFile("交叉操作-----------结束-------");
            FileHelper.writeLogFile("变异操作-----------开始-------");
            // 变异操作
            List<Chromosome> nextPopulation1 = new ArrayList<>();
            for (Chromosome chromosome : nextPopulation) {
                if (rnd.nextDouble() < param.getMutationProb()) {
                    Chromosome chromosome1=  ProductionDeepCopyUtil.deepCopy(chromosome,Chromosome.class);
                    chromosome1.setID(UUID.randomUUID().toString());
                    geneticOps.mutate(chromosome1, globalOpList);
                    nextPopulation1.add(chromosome1);
                }
            }
            nextPopulation.addAll(nextPopulation1);
            FileHelper.writeLogFile("变异操作-----------结束-------");
            FileHelper.writeLogFile("变异批量解码-----------开始-------");



            Chromosomedecode(param,allOperations,globalOpList,nextPopulation);
            FileHelper.writeLogFile("变异批量解码-----------结束-------");
//            // 精英保留
//            List<Chromosome> population1 = population.stream()
//                    .sorted((c1, c2) -> Double.compare(c2.getFitness(), c1.getFitness()))
//                    .collect(Collectors.toList()); // 降序排序
//
//
//            List<Chromosome>   elites = population1.subList(0, param.getElitismCount());

            List<Chromosome> newPopulation = new ArrayList<>();
            //保留一定数量的上一代
            List<Chromosome>  populationcopy = _nsgaIIUtils.selectNextPopulation(combinedFronts, param.getPopulationSize()/5);

            newPopulation.addAll(populationcopy);
            newPopulation.addAll(nextPopulation);
            newPopulation= chromosomeDistinct1(newPopulation);
            FileHelper.writeLogFile("非支配排序-----------开始-------");
            // 2.7 非支配排序
            combinedFronts = _nsgaIIUtils.parallelFastNonDominatedSort(newPopulation);
            FileHelper.writeLogFile("非支配排序-----------结束-------");
            // 2.8 选择下一代种群
            population = _nsgaIIUtils.selectNextPopulation(combinedFronts, param.getPopulationSize());
            // 更新种群
//            population = newPopulation.stream()
//                    .limit(param.getPopulationSize() )
//                    .collect(Collectors.toList());


            best= GetBest(combinedFronts,String.valueOf(iter));
            if(bestFitness<best.getFitness())
            {
                bestFitness=best.getFitness();
                Iteration=1;
            }else {

                Iteration++;
                if (Iteration > 5) {
                    // 当连续 5 代无最优解提升时，降低交叉概率（如从 0.8 降至 0.5）、提高变异概率（如从 0.1 升至 0.2）
                    param.fineTuneParams();
                }
            }
            if(Iteration>10)
            {
                break;
            }
            // 当种群适应度标准差小于阈值（如 0.001）时，说明种群已收敛，提前终止迭代
            fitnessStd = _fitnessCalculator.calculateFitnessStd(population);
            if (fitnessStd < 0.001) {
                FileHelper.writeLogFile("种群已收敛，提前终止迭代");
                break;
            }
            FileHelper.writeLogFile("迭代进化------"+iter+"-----结束-------");

        }

        FileHelper.writeLogFile("迭代进化-----------结束-------");
        best.setBaseTime(param.getBaseTime());
        best.setMaterialIds(materialIds);
        best.setMaterials(null);
        best.setScenarioID(sceneId);
        // best.setOperatRel(_entryRel);

        if(best.getInitMachines()==null)
        {
            best.setInitMachines(ProductionDeepCopyUtil.deepCopyList(machines,Machine.class));
        }

        LocalDateTime endtime=LocalDateTime.now();

        FileHelper.writeLogFile(String.format("排产-----------结束---%s----耗时%d----",allOperations.get(0).getSceneId(),DateTimeUtil.diffDuration(starttime,endtime).getSeconds()) );

        // 步骤3：返回最优解
        return best;

    }

    private Chromosome GetBest(List<List<Chromosome>> fronts,String msg)
    {
        // WriteKpis(fronts,msg);
        List<Chromosome> fChromosomes= fronts.get(0);
        fChromosomes.sort((c1, c2) -> {
            int rankCompare = Double.compare(c1.getCrowdingDistance(), c2.getCrowdingDistance());
            return rankCompare != 0 ? rankCompare : Double.compare(c1.getFitness(), c2.getFitness());
        });
        Chromosome best=fChromosomes.get(0);
        //  WriteKpi(best,"最大");
        return best;
    }
    private List<Chromosome> chromosomeDistinct(List<Chromosome> population)
    {
        if(population==null)
        {
            FileHelper.writeLogFile(String.format("排产-----------方案数量---%d-------",0 ));
            return population;
        }
        population = population.stream()
                .filter(chromosome -> chromosome != null && chromosome.getGeneStr() != null)
                .collect(Collectors.toMap(
                        Chromosome::getGeneStr, // key：去重的字段（GeneStr）
                        u -> u,        // value：Chromosome对象
                        (u1, u2) ->  u1 // 重复时保留第一个元素
                ))
                .values() // 获取去重后的
                .stream()
                .collect(Collectors.toList());

        return  population;
    }
    private List<Chromosome> chromosomeDistinct1(List<Chromosome> population)
    {
        if(population==null)
        {
            FileHelper.writeLogFile(String.format("排产-----------方案数量---%d-------",0 ));
            return population;
        }



        // List<Chromosome>  population1 = population.stream().filter(t->t.getGeneStr()==null).collect(Collectors.toList());

        population = population.stream()
                .collect(Collectors.toMap(
                        Chromosome::getGeneStr, // key：去重的字段（GeneStr）
                        u -> u,        // value：Chromosome对象
                        (u1, u2) -> u1.getFitness() > u2.getFitness() ? u1 : u2 // 重复时保留第一个元素
                ))
                .values() // 获取去重后的
                .stream()
                .collect(Collectors.toList());

        return  population;
    }

    private void  WriteKpis(List<List<Chromosome>> fronts,String index) {
        for (int i=0;i<fronts.size();i++)
        {
            FileHelper.writeLogFile(String.format("KPI---%s--------%d----",index,i));

            for (Chromosome chromosome:fronts.get(i)) {
                WriteKpi(chromosome,"");
            }
        }
    }

    private void  WriteKpi(Chromosome chromosome,String desc)
    {
        FileHelper.writeLogFile(String.format("KPI---%f----%f----%s----%s",chromosome.getWeightedObjective(),chromosome.getFitness(), chromosome.getID(),desc));
        for (double d: chromosome.getObjectives()) {
            FileHelper.writeLogFile(String.format("    KPI---%f-------",d));
        }
    }
    //private ExecutorService decodeExecutor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2);

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

    private  void  Chromosomedecode(ScheduleParams param, List<Entry> allOperations,List<GlobalOperationInfo> globalOpList,List<Chromosome> population)
    {
        FileHelper.writeLogFile("解码---------------"+population.size() );

        GeneticDecoder decoder = new GeneticDecoder(_GlobalParam, param.getBaseTime(), machines, orders, materials, machineScheduler,materialRequirementService, sceneId);
        boolean ismore=false;
        if(ismore) {
            CompletableFuture.allOf(population.stream()
                            .map(chromosome -> CompletableFuture.runAsync(() -> decode(decoder, chromosome, param, allOperations, globalOpList), decodeExecutor))
                            .toArray(CompletableFuture[]::new))
                    .join();

        } else  {
            if (population != null && population.size() > 0) {
                population.forEach(chromosome -> {
                    decode(decoder, chromosome, param, allOperations, globalOpList);
                });
            }
        }


    }

    private  void  decode(GeneticDecoder decoder,Chromosome chromosome,ScheduleParams param, List<Entry> allOperations,List<GlobalOperationInfo> globalOpList) {

        if (chromosome==null){
            System.out.println("chromosome==null");
            return;
        }

        chromosome.setResult(new CopyOnWriteArrayList<>());

        // 假设Machine类有拷贝方法，或使用MapStruct等工具进行映射

        chromosome.setMachines(ProductionDeepCopyUtil.deepCopyList(machines,Machine.class)); // 简单拷贝，实际可能需要深拷贝
        chromosome.setOrders(ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(orders), Order.class) ); // 简单拷贝，实际可能需要深拷贝
        chromosome.setOperatRel(ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(_entryRel), GroupResult.class) ); // 简单拷贝，实际可能需要深拷贝
        chromosome.setMaterials(ProductionDeepCopyUtil.deepCopyTreeMap(materials, String.class,Material.class)); // 简单拷贝，实际可能需要深拷贝

        chromosome.setAllOperations(ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(allOperations), Entry.class) ); // 简单拷贝，实际可能需要深拷贝
        chromosome.setGlobalOpList(ProductionDeepCopyUtil.deepCopyList(new CopyOnWriteArrayList<>(globalOpList), GlobalOperationInfo.class) ); // 简单拷贝，实际可能需要深拷贝
        //chromosome.setObjectiveWeights(_objectiveWeights);
        chromosome.setBaseTime(param.getBaseTime());
        //  chromosome.setInitMachines(ProductionDeepCopyUtil.deepCopyList(machines,Machine.class)); // 简单拷贝，实际可能需要深拷贝
        //   _sceneService.saveChromosomeToFile(chromosome, "12345679");

        // 加载锁定工单到ResultOld
        List<GAScheduleResult> lockedOrders = GlobalCacheUtil.get("locked_orders_" + sceneId);
        if (lockedOrders != null && !lockedOrders.isEmpty()) {
            chromosome.setResultOld(ProductionDeepCopyUtil.deepCopyList(lockedOrders, GAScheduleResult.class));
            FileHelper.writeLogFile("将 " + lockedOrders.size() + " 个锁定工单加载到初始种群中");
        } else {
            chromosome.setResultOld(new CopyOnWriteArrayList<>());
        }

        // 加载锁定工单到ResultOld
//        List<GAScheduleResult> lockedOrders = GlobalCacheUtil.get("locked_orders_" + sceneId);
//        if (lockedOrders != null && !lockedOrders.isEmpty()) {
//            chromosome.setResultOld(ProductionDeepCopyUtil.deepCopyList(lockedOrders, GAScheduleResult.class));
//            FileHelper.writeLogFile("将 " + lockedOrders.size() + " 个锁定工单加载到初始种群中");
//        } else {
//            chromosome.setResultOld(new CopyOnWriteArrayList<>());
//        }

        decoder.decodeChromosomeWithCache(chromosome,false);
        if (chromosome.getFitness() == 0) {
            chromosome.setFitness(_fitnessCalculator.calculateFitness(chromosome, _objectiveWeights));
        }
    }



}
