package com.aps.entity.basic;

import lombok.Data;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Data
public class ScheduleChromosome {
    private List<Gene> genes;
    private List<Order> orders;
    private List<Machine> machines;
    private double fitness;
    private double tardiness;
    private Map<Integer, Double> objectiveValues;
    private LocalDateTime baseTime;
    private long sceneId; // 新增场景ID字段
    public ScheduleChromosome() {
        this.genes = new ArrayList<>();
        this.objectiveValues = new HashMap<>();
    }

    public ScheduleChromosome(LocalDateTime baseTime) {
        this();
        this.baseTime = baseTime;
    }

    // 修改：放宽去重条件，包含更多关键信息
//    public String getGenesStr() {
//        return genes.stream()
//                .sorted(Comparator.comparing(Gene::getOrderId)
//                        .thenComparing(Gene::getOperationId)
//                        .thenComparing(Gene::getStartTime))
//                .map(p -> String.format("%d:%d:%d:%d:%d:%d",
//                        p.getOrderId(), p.getOperationId(), p.getMachineId(),
//                        p.getBatchSize(), p.getStartTime(), p.getEndTime()))
//                .collect(Collectors.joining(";"));
//    }
    public String getGenesStr() {
        return getGenes().stream()
                .sorted(Comparator.comparing(Gene::getOrderId)
                        .thenComparing(Gene::getOperationId)
                        .thenComparing(Gene::getMachineId))
                .map(g -> String.format("%d:%d:%d",
                        g.getOrderId(), g.getOperationId(), g.getMachineId()))
                .collect(Collectors.joining("; "));
    }
    // 新增：生成更详细的键用于调试
    public String getDetailedKey() {
        return genes.stream()
                .sorted(Comparator.comparing(Gene::getOrderId)
                        .thenComparing(Gene::getOperationId)
                        .thenComparing(Gene::getStartTime))
                .map(g -> String.format("O%d-P%d-M%d-B%d-S%d-E%d", 
                        g.getOrderId(), g.getOperationId(), g.getMachineId(),
                        g.getBatchSize(), g.getStartTime(), g.getEndTime()))
                .collect(Collectors.joining("_"));
    }

    public List<Order> getOrders() {
        return calTardiness();
    }

//    private List<Order> calTardiness() {
//        tardiness = 0;
//
//        for (Order order : orders) {
//            final int orderId = order.getId();
//            List<Gene> orderGroups = genes.stream()
//                    .filter(g -> g.getOrderId() == orderId)
//                    .collect(Collectors.toList());
//
//            int orderCompletion = orderGroups.stream()
//                    .mapToInt(Gene::getEndTime)
//                    .max()
//                    .orElse(0);
//
//            LocalDateTime orderCompletionTime = baseTime.plusMinutes(orderCompletion);
//            order.setOrderCompletion(orderCompletionTime);
//            order.setTardiness(0);
//
//            if (orderCompletionTime.isAfter(order.getDueDate().toLocalDateTime())) {
//                long diffHours = java.time.temporal.ChronoUnit.HOURS.between(order.getDueDate(), orderCompletionTime);
//                double tardinessHours = diffHours + (double) java.time.temporal.ChronoUnit.MINUTES.between(order.getDueDate(), orderCompletionTime) % 60 / 60;
//                order.setTardiness(tardinessHours);
//                tardiness += tardinessHours;
//            }
//        }
//        return orders;
//    }

    private List<Order> calTardiness() {
        tardiness = 0;

        for (Order order : orders) {
            final int orderId = order.getId();
            List<Gene> orderGroups = genes.stream()
                    .filter(g -> g.getOrderId() == orderId)
                    .collect(Collectors.toList());

            int orderCompletion = orderGroups.stream()
                    .mapToInt(Gene::getEndTime)
                    .max()
                    .orElse(0);

            LocalDateTime orderCompletionTime = baseTime.plusMinutes(orderCompletion);
            order.setOrderCompletion(orderCompletionTime);
            order.setTardiness(0);

            // 修复：统一时间类型
            LocalDateTime dueDateTime = order.getDueDate().toLocalDateTime();

            if (orderCompletionTime.isAfter(dueDateTime)) {
                // 方法1：使用分钟计算再转换为小时（推荐）
                long totalMinutes = java.time.temporal.ChronoUnit.MINUTES.between(dueDateTime, orderCompletionTime);
                double tardinessHours = totalMinutes / 60.0;

                // 方法2：或者保持原有逻辑但使用统一的时间类型
                // long diffHours = java.time.temporal.ChronoUnit.HOURS.between(dueDateTime, orderCompletionTime);
                // long remainingMinutes = java.time.temporal.ChronoUnit.MINUTES.between(dueDateTime, orderCompletionTime) % 60;
                // double tardinessHours = diffHours + (double) remainingMinutes / 60;

                order.setTardiness(tardinessHours);
                tardiness += tardinessHours;
            }
        }
        return orders;
    }
}