package com.aps.service.impl;

import com.aps.entity.Algorithm.GAScheduleResult;
import com.aps.entity.DiscreteParameterConfigType;
import com.aps.entity.DiscreteParameterDuration;
import com.aps.entity.basic.Entry;
import com.aps.entity.basic.Machine;
import com.aps.mapper.DiscreteParameterDurationMapper;
import com.aps.service.DiscreteParameterDurationService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class DiscreteParameterDurationServiceImpl extends ServiceImpl<DiscreteParameterDurationMapper, DiscreteParameterDuration> implements DiscreteParameterDurationService {

    /**
     * 计算当前工序需要的换型时间
     */
    @Override
    public double calculateChangeoverTime(Entry lastEntry,
                                          Entry entry,
                                          Machine machine,
                                          List<Entry> allOperations,int startTime,List<GAScheduleResult> machineTasks) {

        if (machineTasks==null|| machineTasks.isEmpty()) {
            return 0.0;
        }

        // 获取当前工序的所有参数
        List<ParameterPair> currentParams = getOperationParameters(entry);
        if (currentParams.isEmpty()) {
            return 0.0;
        }






        if (lastEntry == null) {
            return 0.0;
        }

        List<ParameterPair> lastParams = getOperationParameters(lastEntry);
        List<DiscreteParameterDuration> parameterDurations = this.lambdaQuery().list();

        // 获取该设备上的所有任务（按开始时间排序）
        List<GAScheduleResult> machineGenes = machineTasks.stream()
                .filter(g -> g.getMachineId() == machine.getId())
                .sorted(Comparator.comparingInt(GAScheduleResult::getStartTime))
                .collect(Collectors.toList());

        double maxChangeoverTime = 0.0;

        for (ParameterPair currentParam : currentParams) {
            double paramChangeoverTime = calculateChangeoverTimeForParameter(
                    currentParam, lastParams, machineGenes, parameterDurations, startTime, allOperations);

            maxChangeoverTime = Math.max(maxChangeoverTime, paramChangeoverTime);
        }

        return maxChangeoverTime;
    }

    /**
     * 为单个参数计算换型时间
     */
    private double calculateChangeoverTimeForParameter(ParameterPair currentParam,
                                                       List<ParameterPair> lastParams,
                                                       List<GAScheduleResult> machineGenes,
                                                       List<DiscreteParameterDuration> parameterDurations,
                                                       int startTime, List<Entry> allOperations) {

        // 查找相同参数的历史任务链（精确匹配groupid和parameterid）
        List<GAScheduleResult> sameParamTaskChain = findSameParameterTaskChain(currentParam, machineGenes, allOperations);

        if (sameParamTaskChain.isEmpty()) {
            return 0.0;
        }

        // 分别计算四种规则的换型时间
        double changeoverTime1 = calculateByWorkingDuration(currentParam, lastParams, sameParamTaskChain, parameterDurations, allOperations);
        double changeoverTime2 = calculateByAbsoluteDuration(currentParam, lastParams, sameParamTaskChain, parameterDurations, startTime, allOperations);
        double changeoverTime3 = calculateByMaxInterval(currentParam, lastParams, sameParamTaskChain, parameterDurations, startTime, allOperations);
        double changeoverTime4 = calculateByOrderCount(currentParam, lastParams, sameParamTaskChain, parameterDurations, allOperations);
        double changeoverTime5 = calculateByAccumulatedQuantity(currentParam, lastParams, sameParamTaskChain, parameterDurations, allOperations);

        // 取五种规则中的最大值
        return Math.max(Math.max(Math.max(changeoverTime1, changeoverTime2), Math.max(changeoverTime3, changeoverTime4)),
                changeoverTime5);

    }

    /**
     * 规则1：工作时间长检查（精确匹配参数）
     */
    private double calculateByWorkingDuration(ParameterPair currentParam, List<ParameterPair> lastParams,
                                              List<GAScheduleResult> sameParamChain,
                                              List<DiscreteParameterDuration> parameterDurations,
                                              List<Entry> allOperations) {

        DiscreteParameterDuration config = findParameterConfig(currentParam, DiscreteParameterConfigType.WORKING_DURATION, parameterDurations);
        if (config == null) {
            return 0.0;
        }

        long maxWorkingSeconds = config.getMeasureduration().longValue();

        // 从后往前找最近的换型点
        int lastChangeoverIndex = findLastChangeoverIndex(sameParamChain);

        // 计算从换型点之后的总工作时间（只计算精确匹配的任务）
        long totalWorkingSeconds = 0;
        for (int i = lastChangeoverIndex + 1; i < sameParamChain.size(); i++) {
            GAScheduleResult task = sameParamChain.get(i);

            // 验证任务参数是否精确匹配当前参数
            if (isExactParameterMatch(task, currentParam, allOperations)) {
                totalWorkingSeconds += (task.getEndTime() - task.getStartTime());
            } else {
                // 遇到不匹配的任务，停止累计（因为参数已变化）
                break;
            }
        }

        if (totalWorkingSeconds >= maxWorkingSeconds) {
            return calculateMaxChangeoverDuration(lastParams, currentParam, parameterDurations);
        }

        return 0.0;
    }

    /**
     * 规则2：绝对工作时间长检查（精确匹配参数）
     */
    private double calculateByAbsoluteDuration(ParameterPair currentParam, List<ParameterPair> lastParams,
                                               List<GAScheduleResult> sameParamChain,
                                               List<DiscreteParameterDuration> parameterDurations,
                                               int startTime, List<Entry> allOperations) {

        DiscreteParameterDuration config = findParameterConfig(currentParam, DiscreteParameterConfigType.ABSOLUTE_DURATION, parameterDurations);
        if (config == null) {
            return 0.0;
        }

        if (sameParamChain.isEmpty()) {
            return 0.0;
        }

        // 从后往前找最近的换型点
        int lastChangeoverIndex = findLastChangeoverIndex(sameParamChain);

        // 找到第一个精确匹配参数的任务
        GAScheduleResult startTask = findFirstExactMatchTask(sameParamChain, currentParam, lastChangeoverIndex, allOperations);
        if (startTask == null) {
            return 0.0;
        }

        long absoluteDurationSeconds = calculateAbsoluteDuration(startTask, startTime);
        long maxAbsoluteSeconds = config.getMeasureduration().longValue();

        if (absoluteDurationSeconds >= maxAbsoluteSeconds) {
            return calculateMaxChangeoverDuration(lastParams, currentParam, parameterDurations);
        }

        return 0.0;
    }

    /**
     * 规则3：工作间隔时间检查（精确匹配参数）
     */
    private double calculateByMaxInterval(ParameterPair currentParam, List<ParameterPair> lastParams,
                                          List<GAScheduleResult> sameParamChain,
                                          List<DiscreteParameterDuration> parameterDurations,
                                          int startTime, List<Entry> allOperations) {

        DiscreteParameterDuration config = findParameterConfig(currentParam, DiscreteParameterConfigType.MAX_INTERVAL, parameterDurations);
        if (config == null) {
            return 0.0;
        }

        if (sameParamChain.isEmpty()) {
            return 0.0;
        }

        // 找到最后一个精确匹配参数的任务
        GAScheduleResult lastTask = findLastExactMatchTask(sameParamChain, currentParam, allOperations);
        if (lastTask == null) {
            return 0.0;
        }

        // 计算从上一个任务结束到当前开始时间的间隔
        long intervalSeconds = startTime - lastTask.getEndTime();
        long maxIntervalSeconds = config.getMeasureduration().longValue();

        if (intervalSeconds > maxIntervalSeconds) {
            return calculateMaxChangeoverDuration(lastParams, currentParam, parameterDurations);
        }

        return 0.0;
    }

    /**
     * 规则4：工单数量换型检查（精确匹配参数）
     */
    private double calculateByOrderCount(ParameterPair currentParam, List<ParameterPair> lastParams,
                                         List<GAScheduleResult> sameParamChain,
                                         List<DiscreteParameterDuration> parameterDurations,
                                         List<Entry> allOperations) {

        DiscreteParameterDuration config = findParameterConfig(currentParam, DiscreteParameterConfigType.ORDER_COUNT, parameterDurations);
        if (config == null) {
            return 0.0;
        }

        // 获取配置的工单数量阈值
        int maxOrderCount = config.getMeasureduration().intValue();

        // 计算从最近换型点之后，精确匹配参数的任务数量
        int orderCount = calculateOrderCountSinceLastChangeover(currentParam, sameParamChain, allOperations);

        if (orderCount >= maxOrderCount) {
            return calculateMaxChangeoverDuration(lastParams, currentParam, parameterDurations);
        }

        return 0.0;
    }

    /**
     * 查找相同参数的任务链（精确匹配groupid和parameterid）
     */
    private List<GAScheduleResult> findSameParameterTaskChain(ParameterPair targetParam,
                                                              List<GAScheduleResult> machineGenes,
                                                              List<Entry> allOperations) {
        List<GAScheduleResult> sameParamChain = new ArrayList<>();

        // 从最新的任务开始往前找
        for (int i = machineGenes.size() - 1; i >= 0; i--) {
            GAScheduleResult gene = machineGenes.get(i);

            // 精确匹配：groupid和parameterid都必须相同
            if (isExactParameterMatch(gene, targetParam, allOperations)) {
                sameParamChain.add(0, gene); // 添加到开头保持时间顺序

                // 如果这个任务有换型，停止追溯（换型后重新计算）
                if (gene.getChangeOverTime() > 0) {
                    break;
                }
            } else {
                break; // 遇到不同参数的任务，停止追溯
            }
        }

        return sameParamChain;
    }

    /**
     * 检查任务参数是否精确匹配目标参数
     */
    private boolean isExactParameterMatch(GAScheduleResult task, ParameterPair targetParam, List<Entry> allOperations) {
        List<ParameterPair> taskParams = getGeneParameters(task, allOperations);
        return taskParams.stream()
                .anyMatch(param -> param.getGroupId().equals(targetParam.getGroupId()) &&
                        param.getParameterId().equals(targetParam.getParameterId()));
    }

    /**
     * 找到第一个精确匹配参数的任务
     */
    private GAScheduleResult findFirstExactMatchTask(List<GAScheduleResult> sameParamChain,
                                                     ParameterPair targetParam,
                                                     int lastChangeoverIndex,
                                                     List<Entry> allOperations) {
        for (int i = lastChangeoverIndex + 1; i < sameParamChain.size(); i++) {
            GAScheduleResult task = sameParamChain.get(i);
            if (isExactParameterMatch(task, targetParam, allOperations)) {
                return task;
            }
        }
        return null;
    }

    /**
     * 找到最后一个精确匹配参数的任务
     */
    private GAScheduleResult findLastExactMatchTask(List<GAScheduleResult> sameParamChain,
                                                    ParameterPair targetParam,
                                                    List<Entry> allOperations) {
        for (int i = sameParamChain.size() - 1; i >= 0; i--) {
            GAScheduleResult task = sameParamChain.get(i);
            if (isExactParameterMatch(task, targetParam, allOperations)) {
                return task;
            }
        }
        return null;
    }

    /**
     * 计算从最近换型点之后，精确匹配参数的任务数量
     */
    private int calculateOrderCountSinceLastChangeover(ParameterPair targetParam,
                                                       List<GAScheduleResult> sameParamChain,
                                                       List<Entry> allOperations) {

        // 从后往前找最近的换型点
        int lastChangeoverIndex = findLastChangeoverIndex(sameParamChain);

        int validOrderCount = 0;

        // 从换型点之后开始统计
        for (int i = lastChangeoverIndex + 1; i < sameParamChain.size(); i++) {
            GAScheduleResult task = sameParamChain.get(i);

            // 只统计精确匹配参数的任务
            if (isExactParameterMatch(task, targetParam, allOperations)) {
                validOrderCount++;
            } else {
                // 遇到不匹配的参数，停止计数（因为参数已变化）
                break;
            }
        }

        return validOrderCount;
    }

    /**
     * 找到最近的换型点索引
     */
    private int findLastChangeoverIndex(List<GAScheduleResult> taskChain) {
        for (int i = taskChain.size() - 1; i >= 0; i--) {
            if (taskChain.get(i).getChangeOverTime() > 0) {
                return i;
            }
        }
        return -1;
    }

    /**
     * 计算绝对时间跨度
     */
    private long calculateAbsoluteDuration(GAScheduleResult task, int startTime) {
        return startTime - task.getStartTime();
    }

    /**
     * 计算与所有历史参数的最大换型时间
     */
    private double calculateMaxChangeoverDuration(List<ParameterPair> fromParams, ParameterPair toParam,
                                                  List<DiscreteParameterDuration> parameterDurations) {
        if (fromParams.isEmpty()) {
            return 0.0;
        }

        double maxChangeoverTime = 0.0;
        for (ParameterPair fromParam : fromParams) {
            if (fromParam.equals(toParam)) {
                continue;
            }
            double changeoverTime = getChangeoverDuration(fromParam, toParam, parameterDurations);
            maxChangeoverTime = Math.max(maxChangeoverTime, changeoverTime);
        }
        return maxChangeoverTime;
    }

    // 其他辅助方法保持不变...
    private List<ParameterPair> getGeneParameters(GAScheduleResult gene, List<Entry> allOperations) {
        Entry prev = allOperations.stream()
                .filter(t -> t.getExecId().equals(gene.getExecId()))
                .findFirst().orElse(null);
        if (prev == null || prev.getDiscreteParameter() == null) {
            return new ArrayList<>();
        }
        return prev.getDiscreteParameter().stream()
                .map(param -> new ParameterPair(param.getGroupId(), param.getParameterId()))
                .filter(pair -> pair.getGroupId() != null && pair.getParameterId() != null)
                .collect(Collectors.toList());
    }

    private List<ParameterPair> getOperationParameters(Entry operation) {
        if (operation == null || operation.getDiscreteParameter() == null) {
            return new ArrayList<>();
        }
        return operation.getDiscreteParameter().stream()
                .map(param -> new ParameterPair(param.getGroupId(), param.getParameterId()))
                .filter(pair -> pair.getGroupId() != null && pair.getParameterId() != null)
                .collect(Collectors.toList());
    }

    private DiscreteParameterDuration findParameterConfig(ParameterPair param, DiscreteParameterConfigType configType,
                                                          List<DiscreteParameterDuration> parameterDurations) {
        return parameterDurations.stream()
                .filter(pd -> param.getGroupId().equals(pd.getGroupid()) &&
                        param.getParameterId().equals(pd.getParameterid()) &&
                        configType.getValue()==pd.getMeasureparameterid())
                .findFirst()
                .orElse(null);
    }

    private double getChangeoverDuration(ParameterPair fromParam, ParameterPair toParam,
                                         List<DiscreteParameterDuration> parameterDurations) {
        return parameterDurations.stream()
                .filter(pd -> fromParam.getGroupId().equals(pd.getGroupid()) &&
                        fromParam.getParameterId().equals(pd.getParameterid()) &&
                        toParam.getParameterId().equals(pd.getExp2()))
                .findFirst()
                .map(pd -> pd.getMeasureduration().doubleValue())
                .orElse(0.0);
    }





    /**
     * 规则5：累计数量换型检查
     * 例如：累计生产数量达到2500就需要换型
     */
    private double calculateByAccumulatedQuantity(ParameterPair currentParam, List<ParameterPair> lastParams,
                                                  List<GAScheduleResult> sameParamChain,
                                                  List<DiscreteParameterDuration> parameterDurations,
                                                  List<Entry> allOperations) {

        DiscreteParameterDuration config = findParameterConfig(currentParam, DiscreteParameterConfigType.WORKING_QUANTITY, parameterDurations);
        if (config == null) {
            return 0.0;
        }

        // 获取配置的累计数量阈值
        double maxQuantity = config.getMeasureduration().doubleValue();

        // 计算从最近换型点之后的累计数量
        double accumulatedQuantity = calculateAccumulatedQuantitySinceLastChangeover(currentParam, sameParamChain, allOperations);

        if (accumulatedQuantity >= maxQuantity) {
            return calculateMaxChangeoverDuration(lastParams, currentParam, parameterDurations);
        }

        return 0.0;
    }

    /**
     * 计算从最近换型点之后，精确匹配参数的累计数量
     */
    private double calculateAccumulatedQuantitySinceLastChangeover(ParameterPair targetParam,
                                                                   List<GAScheduleResult> sameParamChain,
                                                                   List<Entry> allOperations) {

        // 从后往前找最近的换型点
        int lastChangeoverIndex = findLastChangeoverIndex(sameParamChain);

        double accumulatedQuantity = 0.0;

        // 从换型点之后开始统计
        for (int i = lastChangeoverIndex + 1; i < sameParamChain.size(); i++) {
            GAScheduleResult task = sameParamChain.get(i);

            // 只统计精确匹配参数的任务数量
            if (isExactParameterMatch(task, targetParam, allOperations)) {
                accumulatedQuantity += getTaskQuantity(task, allOperations);
            } else {
                // 遇到不匹配的参数，停止累计（因为参数已变化）
                break;
            }
        }

        return accumulatedQuantity;
    }

    /**
     * 获取任务的数量
     */
    private double getTaskQuantity(GAScheduleResult task, List<Entry> allOperations) {
        Entry entry = allOperations.stream()
                .filter(t -> t.getExecId().equals(task.getExecId()))
                .findFirst().orElse(null);

        return entry != null ? entry.getQuantity() : 0.0;
    }
    /**
     * 参数对封装类
     */
    private static class ParameterPair {
        private final String groupId;
        private final String parameterId;

        public ParameterPair(String groupId, String parameterId) {
            this.groupId = groupId;
            this.parameterId = parameterId;
        }

        public String getGroupId() { return groupId; }
        public String getParameterId() { return parameterId; }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            ParameterPair that = (ParameterPair) o;
            return Objects.equals(groupId, that.groupId) &&
                    Objects.equals(parameterId, that.parameterId);
        }

        @Override
        public int hashCode() {
            return Objects.hash(groupId, parameterId);
        }

        @Override
        public String toString() {
            return groupId + ":" + parameterId;
        }
    }
}