package com.zehong.system.task;

import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Date;

/**
 * @author lenovo
 * @date 2025/6/25
 * @description 定时调度任务
 */
@Service
public class DeviceTaskScheduler {

    private static final Logger log = LoggerFactory.getLogger(DeviceTaskScheduler.class);
    @Resource
    private Scheduler scheduler;

    // 任务组名（统一固定，与原有逻辑保持一致）
    private static final String JOB_GROUP = "DEVICE_TASKS";
    // 触发器组名（统一固定，与原有逻辑保持一致）
    private static final String TRIGGER_GROUP = "DEVICE_TRIGGERS";
    /**
     * 创建设备监控任务
     * @param fStoreyId 设备ID
     */
    public void scheduleDeviceMonitoring(Long fStoreyId,String fPowerOutageIp,Integer fPowerOutagePort) throws SchedulerException {

        // 2. 创建每小时通信任务
        createHourlyCommunicationJob(fStoreyId);

        // 3. 创建71小时后执行任务
        createFinalExecutionJob(fStoreyId,fPowerOutageIp,fPowerOutagePort);
    }

    /**
     * 创建每小时通信任务
     */
    private void createHourlyCommunicationJob(Long fStoreyId) throws SchedulerException {
        // 1. 构建任务唯一标识（JobKey = jobId + 任务组名）
        String jobId = "COMM_" + fStoreyId;
        JobKey jobKey = new JobKey(jobId, JOB_GROUP);
        // 构建触发器唯一标识（TriggerKey = jobId + "_TRIGGER" + 触发器组名）
        TriggerKey triggerKey = new TriggerKey(jobId + "_TRIGGER", TRIGGER_GROUP);

        // 2. 准备JobDetail（与原有逻辑一致，仅初始化不提交）
        String fStoreyIdStr = fStoreyId.toString();
        JobDetail job = JobBuilder.newJob(DeviceCommunicationJob.class)
                .withIdentity(jobKey) // 直接用构建好的JobKey，避免重复编码
                .usingJobData("fStoreyId", fStoreyIdStr)
                .storeDurably() // 保留原有持久化配置
                .build();

        // 3. 准备新触发器（Cron调度，与原有逻辑一致）
        Trigger newTrigger = TriggerBuilder.newTrigger()
                .withIdentity(triggerKey) // 用构建好的TriggerKey
                .withSchedule(CronScheduleBuilder.cronSchedule("0 0/2 * * * ?")) // 测试每2分钟执行，后续可改回0 0 * * * ?
                .build();

        // 4. 分场景处理：存在则更新，不存在则创建
        if (scheduler.checkExists(jobKey)) {
            // 任务已存在：更新触发器（替换旧触发器为新触发器）
            Date updatedTime = scheduler.rescheduleJob(triggerKey, newTrigger);
            log.info("每小时通信任务[{}]已存在，成功更新触发器，下次执行时间：{}", jobId, updatedTime);
        } else {
            // 任务不存在：创建JobDetail和触发器
            scheduler.scheduleJob(job, newTrigger);
            log.info("每小时通信任务[{}]不存在，成功创建任务及触发器", jobId);
        }
    }

    /**
     * 创建71小时后执行任务
     */
    private void createFinalExecutionJob(Long fStoreyId,String fPowerOutageIp,Integer fPowerOutagePort) throws SchedulerException {
        // 1. 构建任务唯一标识（JobKey = jobId + 任务组名）
        String jobId = "FINAL_" + fStoreyId;
        JobKey jobKey = new JobKey(jobId, JOB_GROUP);
        // 构建触发器唯一标识（TriggerKey = jobId + "_TRIGGER" + 触发器组名）
        TriggerKey triggerKey = new TriggerKey(jobId + "_TRIGGER", TRIGGER_GROUP);

        // 2. 准备JobDetail（与原有逻辑一致，仅初始化不提交）
        String fStoreyIdStr = fStoreyId.toString();
        String fPowerOutagePortStr = fPowerOutagePort.toString();
        JobDetail job = JobBuilder.newJob(FinalExecutionJob.class)
                .withIdentity(jobKey) // 直接用构建好的JobKey
                .usingJobData("fStoreyId", fStoreyIdStr)
                .usingJobData("fPowerOutageIp", fPowerOutageIp)
                .usingJobData("fPowerOutagePort", fPowerOutagePortStr)
                .storeDurably() // 保留原有持久化配置
                .build();

        // 3. 准备新触发器（定时一次执行，测试用10分钟后，后续可改回71小时）
        Date executeTime = Date.from(Instant.now().plus(10, ChronoUnit.MINUTES)); // 测试用10分钟，正式环境改71
        Trigger newTrigger = TriggerBuilder.newTrigger()
                .withIdentity(triggerKey) // 用构建好的TriggerKey
                .startAt(executeTime) // 指定执行时间（一次触发）
                .build();

        // 4. 分场景处理：存在则更新，不存在则创建
        if (scheduler.checkExists(jobKey)) {
            // 任务已存在：更新触发器（重新指定执行时间）
            Date updatedTime = scheduler.rescheduleJob(triggerKey, newTrigger);
            log.info("71小时后执行任务[{}]已存在，成功更新触发器，新执行时间：{}", jobId, updatedTime);
        } else {
            // 任务不存在：创建JobDetail和触发器
            scheduler.scheduleJob(job, newTrigger);
            log.info("71小时后执行任务[{}]不存在，成功创建任务及触发器，执行时间：{}", jobId, executeTime);
        }
    }
}
