package com.aps.service.plan;

import com.aps.common.util.JsonFileReader;
import com.aps.controller.gantt.FileUploadController;
import com.aps.entity.Schedule.GenVO;
import com.aps.entity.Schedule.MachineVO;
import com.aps.entity.basic.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class PlanResultService {
    // 注入FileUploadController
    @Autowired
    private FileUploadController fileUploadController;
    
    private final LocalDateTime baseTime = LocalDateTime.of(2025, 10, 1, 0, 0, 0);

    public List<ScheduleChromosome> execute() {
        try {
            // 1. 读取数据
            List<Machine> machines = loadData("machines.json", Machine.class);
            List<Product> products = loadData("products.json", Product.class);
            List<Order> orders = loadData("orders.json", Order.class);
            
            // 设置机器信息到班次中
            for (Machine machine : machines) {
                if (machine.getShifts() != null) {
                    for (Shift shift : machine.getShifts()) {
                        shift.setMachineId(machine.getId());
                        shift.setMachineName(machine.getName());
                    }
                }
                
                // 调试：打印机器和班次信息
                System.out.println("Machine: " + machine.getId() + ", Name: " + machine.getName());
                if (machine.getShifts() != null) {
                    for (Shift shift : machine.getShifts()) {
                        System.out.println("  Shift: " + shift.getStartTime() + " - " + shift.getEndTime() + 
                                         ", Status: " + shift.getStatus() +
                                         ", MachineId: " + shift.getMachineId() +
                                         ", MachineName: " + shift.getMachineName());
                    }
                }
            }
            
            // 创建节假日
            List<Holiday> holidays = Arrays.asList(
                    new Holiday(LocalDateTime.of(2025, 10, 1, 0, 0),
                            LocalDateTime.of(2025, 10, 7, 23, 59))
            );
            
            // 将节假日添加到所有设备中
            addHolidaysToAllMachines(machines, holidays);

            // 3. 创建调度服务
            MachineSchedulerService machineScheduler = new MachineSchedulerService(
                    holidays, LocalDateTime.of(2025, 10, 1, 0, 0, 0));

            // 4. 初始化机器时间线
            for (Machine machine : machines) {
                MachineTimeline timeline = machineScheduler.getOrCreateTimeline(machine);
                machine.setAvailability(timeline.getSegments());
            }

            // 5. 执行调度算法
            AlgorithmScheduler7 scheduler = new AlgorithmScheduler7(products, machines, orders, machineScheduler);
            List<ScheduleChromosome> scheduleChromosomes = scheduler.RunAll();
            
            // 对调度结果按照 fitness 由高到低排序
            scheduleChromosomes.sort((c1, c2) -> Double.compare(c2.getFitness(), c1.getFitness()));
            
            // 为每个 ScheduleChromosome 分配场景ID（基于排序后的位置）
            for (int i = 0; i < scheduleChromosomes.size(); i++) {
                scheduleChromosomes.get(i).setSceneId(i + 1); // 场景ID从1开始
            }

            return scheduleChromosomes;

        } catch (Exception e) {
            throw new RuntimeException("调度执行失败", e);
        }
    }

    /**
     * 加载数据，优先从上传文件夹加载，如果不存在则从resources加载
     *
     * @param fileName 文件名
     * @param clazz    类型
     * @param <T>      泛型
     * @return 数据列表
     * @throws IOException IO异常
     */
    private <T> List<T> loadData(String fileName, Class<T> clazz) throws IOException {
        // 检查是否有上传的文件
        if (fileUploadController.isFileUploaded(fileName)) {
            String filePath = fileUploadController.getUploadedFilePath(fileName);
            return JsonFileReader.readListFromFile(filePath, clazz);
        } else {
            // 使用默认的resources文件
            return JsonFileReader.readListFromResources(fileName, clazz);
        }
    }
    
    /**
     * 将假期添加到所有设备的维护窗口中
     * @param machines 设备列表
     * @param holidays 假期列表
     */
    private void addHolidaysToAllMachines(List<Machine> machines, List<Holiday> holidays) {
        if (machines == null || holidays == null) {
            return;
        }
        
        for (Machine machine : machines) {
            // 确保维护窗口列表不为null
            if (machine.getMaintenanceWindows() == null) {
                machine.setMaintenanceWindows(new ArrayList<>());
            }
            
            for (Holiday holiday : holidays) {
                // 将假期转换为维护窗口并添加到设备中
                MaintenanceWindow maintenanceWindow = new MaintenanceWindow(holiday, "Holiday Period");
                machine.addMaintenanceWindow(maintenanceWindow);
            }
        }
    }

    public GenVO convertGeneToGenVO(Gene gene, LocalDateTime baseTime) {
        GenVO genVO = new GenVO();
        genVO.setOrderId(String.valueOf(gene.getOrderId()));
        genVO.setOperationId(gene.getOperationId());
        genVO.setEquipId(gene.getMachineId());
        genVO.setQuantity(BigDecimal.valueOf(gene.getBatchSize()));
        genVO.setStartTime(baseTime.plusMinutes(gene.getStartTime()));
        genVO.setEndTime(baseTime.plusMinutes(gene.getEndTime()));
        genVO.setOperationName(""); // 从其他数据源获取
        genVO.setEquipName(""); // 从其他数据源获取
        return genVO;
    }

    // 批量转换
    public List<GenVO> convertGeneListToGenVO(List<Gene> geneList, LocalDateTime baseTime) {
        return geneList.stream()
                .map(gene -> convertGeneToGenVO(gene, baseTime))
                .collect(Collectors.toList());
    }
    
    public List<MachineVO> convertMachineListToVO(List<Machine> machines) {
        return machines.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }
    
    private MachineVO convertToVO(Machine machine) {
        MachineVO machineVO = new MachineVO();
        machineVO.setId(machine.getId());
        machineVO.setEquipId(String.valueOf(machine.getId()));
        machineVO.setEquipName(machine.getName());
        // 注意：tasks 字段需要在其他地方设置，因为 Machine 类中没有任务信息
        return machineVO;
    }
}