// TaskSchedulerManager.java
package cn.iocoder.yudao.module.iot.controller.admin.device.scheduled.scheduler;

import cn.iocoder.yudao.module.iot.controller.admin.device.enums.TaskTypeEnum;
import cn.iocoder.yudao.module.iot.controller.admin.device.scheduled.core.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.scheduling.support.PeriodicTrigger;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.time.Duration;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

@Component
public class TaskSchedulerManager {
    private static final Logger logger = LoggerFactory.getLogger(TaskSchedulerManager.class);

    private final TaskScheduler taskScheduler;

    // 存储所有任务
    private final Map<String, Task> taskBeans = new ConcurrentHashMap<>();

    // 存储正在运行的任务
    private final Map<Long, ScheduledFuture<?>> runningTasks = new ConcurrentHashMap<>();
    private final Map<Long, TaskInfo> taskInfos = new ConcurrentHashMap<>();

    // 任务信息类
    private static class TaskInfo {
        private Long taskId;
        private String taskType;
        private String taskParam;
        private String cronExpression;
        private String scheduleType; // "CRON" 或 "FIXED_RATE" 或 "FIXED_DELAY"
        private Long initialDelay;
        private Long period;
        private TimeUnit timeUnit;

        // 构造器
        public TaskInfo(Long taskId, String taskType, String taskParam) {
            this.taskId = taskId;
            this.taskType = taskType;
            this.taskParam = taskParam;
        }

        // getters and setters...
    }

    // 通过构造器注入
    public TaskSchedulerManager(TaskScheduler taskScheduler,
                                @Autowired(required = false) java.util.List<Task> tasks) {
        this.taskScheduler = taskScheduler;

        // 注册所有任务
        if (tasks != null) {
            for (Task task : tasks) {
                taskBeans.put(task.getTaskType(), task);
                logger.info("注册任务类型: {}", task.getTaskType());
            }
        }
    }

    /**
     * 启动 Cron 定时任务
     */
    public boolean startCronTask(Long taskId, String taskType, String taskParam, String cronExpression) {
        return startTask(taskId, taskType, taskParam, "CRON", cronExpression, null, null, null);
    }

    /**
     * 启动固定频率任务
     */
    public boolean startFixedRateTask(Long taskId, String taskType, String taskParam,
                                      long initialDelay, long period, TimeUnit timeUnit) {
        return startTask(taskId, taskType, taskParam, "FIXED_RATE", null,
                initialDelay, period, timeUnit);
    }

    /**
     * 启动固定延迟任务
     */
    public boolean startFixedDelayTask(Long taskId, String taskType, String taskParam,
                                       long initialDelay, long period, TimeUnit timeUnit) {
        return startTask(taskId, taskType, taskParam, "FIXED_DELAY", null,
                initialDelay, period, timeUnit);
    }

    /**
     * 通用启动任务方法
     */
    private boolean startTask(Long taskId, String taskType, String taskParam,
                              String scheduleType, String cronExpression,
                              Long initialDelay, Long period, TimeUnit timeUnit) {
        try {
            // 停止已存在的任务
            stopTask(taskId);

            // 获取任务实例
            Task task = taskBeans.get(taskType);
            if (task == null) {
                logger.error("任务类型不存在: {}", taskType);
                return false;
            }

            // 创建任务信息
            TaskInfo taskInfo = new TaskInfo(taskId, taskType, taskParam);
            taskInfo.scheduleType = scheduleType;
            taskInfo.cronExpression = cronExpression;
            taskInfo.initialDelay = initialDelay;
            taskInfo.period = period;
            taskInfo.timeUnit = timeUnit;
            taskInfos.put(taskId, taskInfo);

            // 根据调度类型创建任务
            ScheduledFuture<?> future = null;
            switch (scheduleType) {
                case "CRON":
                    future = taskScheduler.schedule(
                            () -> task.execute(taskId, taskParam),
                            new CronTrigger(cronExpression)
                    );
                    break;

                case "FIXED_RATE":
                    if (initialDelay != null && period != null && timeUnit != null) {
                        future = taskScheduler.scheduleAtFixedRate(
                                () -> task.execute(taskId, taskParam),
                                initialDelay
                        );
                    }
                    break;

                case "FIXED_DELAY":
                    if (initialDelay != null && period != null && timeUnit != null) {
                        future = taskScheduler.scheduleWithFixedDelay(
                                () -> task.execute(taskId, taskParam),
                                initialDelay
                        );
                    }
                    break;
            }

            if (future != null) {
                runningTasks.put(taskId, future);
                logger.info("启动{}任务成功，任务ID: {}, 类型: {}, 参数: {}",
                        scheduleType, taskId, taskType, taskParam);
                return true;
            }

            return false;

        } catch (Exception e) {
            logger.error("启动任务失败，任务ID: {}", taskId, e);
            return false;
        }
    }

    // TaskSchedulerManager.java
    public boolean stopTask(Long taskId) {
        try {
            ScheduledFuture<?> future = runningTasks.get(taskId);
            if (future != null) {
                future.cancel(true);
                runningTasks.remove(taskId);
                taskInfos.remove(taskId);
                logger.info("停止任务成功，任务ID: {}", taskId);
                return true;
            }
            return false;
        } catch (Exception e) {
            logger.error("停止任务失败，任务ID: {}", taskId, e);
            return false;
        }
    }

    /**
     * 获取任务信息
     */
    public TaskInfo getTaskInfo(Long taskId) {
        return taskInfos.get(taskId);
    }

    /**
     * 检查任务是否运行
     */
    public boolean isTaskRunning(Long taskId) {
        ScheduledFuture<?> future = runningTasks.get(taskId);
        return future != null && !future.isCancelled() && !future.isDone();
    }

    /**
     * 获取所有任务类型
     */
    public Map<String, Task> getAllTaskTypes() {
        return new ConcurrentHashMap<>(taskBeans);
    }

    /**
     * 获取运行中的任务数量
     */
    public int getRunningTaskCount() {
        return runningTasks.size();
    }

    /**
     * 停止所有任务
     */
    public void stopAllTasks() {
        logger.info("停止所有定时任务，共 {} 个", runningTasks.size());
        for (Long taskId : runningTasks.keySet()) {
            stopTask(taskId);
        }
    }

//    /**
//     * 原设备任务方法（保持兼容性）
//     */
//    public boolean startDeviceTask(Long deviceId, String deviceCode, String cronExpression) {
//        String taskParam = deviceId + ":" + deviceCode;
//        return startCronTask(deviceId, TaskTypeEnum.DEVICE.getCode(), taskParam, cronExpression);
//    }

    /**
     * 启动设备任务
     */
    public boolean startDeviceTask(Long deviceId, String cronExpression) {
        Long taskId = TaskTypeEnum.DEVICE.generateTaskId(deviceId);
        return startCronTask(taskId, TaskTypeEnum.DEVICE.getCode(),
                "device:" + deviceId, cronExpression);
    }

    /**
     * 停止设备任务
     */
    public boolean stopDeviceTask(Long deviceId) {
        if (deviceId == null) {
            logger.warn("设备ID不能为空");
            return false;
        }

        // 生成与启动时相同的任务ID
        Long taskId = TaskTypeEnum.DEVICE.generateTaskId(deviceId);
        logger.info("停止设备任务，设备ID: {}, 生成的任务ID: {}", deviceId, taskId);

        return stopTask(taskId);
    }


    /**
     * 启动工单任务
     */
    public boolean startWorkOrderTask(Long configId, String cronExpression) {
        Long taskId = TaskTypeEnum.WORK_ORDER.generateTaskId(configId);
        return startCronTask(taskId, TaskTypeEnum.WORK_ORDER.getCode(),
                "workOrder:" + configId, cronExpression);
    }


    /**
     * 停止工单任务
     */
    public boolean stopWorkOrderTask(Long configId) {
        if (configId == null) {
            logger.warn("工单配置ID不能为空");
            return false;
        }

        // 生成与启动时相同的任务ID
        Long taskId = TaskTypeEnum.WORK_ORDER.generateTaskId(configId);
        logger.info("停止工单任务，配置ID: {}, 生成的任务ID: {}", configId, taskId);

        return stopTask(taskId);
    }
}