package cd.casic.ci.process.engine.scheduler.config;

import cd.casic.ci.process.engine.scheduler.dao.PipelineSchedulingPropertiesDao;
import cd.casic.ci.process.engine.scheduler.dateObject.PipelineSchedulingProperties;
import cd.casic.ci.process.engine.scheduler.job.PipelineSchedulingJob;
import cd.casic.ci.process.engine.scheduler.req.PipelineSchedulingReq;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.List;

import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;

/**
 * @author HopeLi
 * @version v1.0
 * @ClassName QuartzSchedulerManager
 * @Date: 2025/5/27 17:31
 * @Description:
 */

@Component
@Slf4j
public class QuartzSchedulerManager {
    private static final String JOB_GROUP_NAME = "PIPELINE_JOB_GROUP";
    private static final String TRIGGER_GROUP_NAME = "PIPELINE_TRIGGER_GROUP";

    @Resource
    private Scheduler scheduler;

    @Resource
    private PipelineSchedulingPropertiesDao pipelineSchedulingPropertiesDao;

    @PostConstruct
    public void init() throws SchedulerException {
        log.info("Quartz 调度器初始化完成");
    }

    /**
     * 添加一个定时任务
     */
    public void addTask(PipelineSchedulingReq req) throws Exception {
        JobDetail jobDetail = newJob(PipelineSchedulingJob.class)
                .withIdentity(req.getPipelineId(), JOB_GROUP_NAME)
                .usingJobData(PipelineSchedulingJob.JOB_PARAM_PIPELINE_ID, req.getPipelineId())
                .build();

        Trigger trigger = newTrigger()
                .withIdentity(req.getPipelineId(), TRIGGER_GROUP_NAME)
                .withSchedule(CronScheduleBuilder.cronSchedule(req.getCron()))
                .build();

        scheduler.scheduleJob(jobDetail, trigger);
        log.info("任务 [{}] 已添加，cron: {}", req.getPipelineId(), req.getCron());

        QueryWrapper<PipelineSchedulingProperties> wrapper = new QueryWrapper<>();
        wrapper.eq("pipeline_id", req.getPipelineId());
        wrapper.eq("cron",  req.getCron());
        List<PipelineSchedulingProperties> list = pipelineSchedulingPropertiesDao.selectList(wrapper);

        //为空则数据入库，否则仅为重新添加任务进调度器
        if (CollectionUtils.isEmpty(list)){
            PipelineSchedulingProperties pipelineSchedulingProperties = new PipelineSchedulingProperties();
            pipelineSchedulingProperties.setPipelineId(req.getPipelineId());
            pipelineSchedulingProperties.setCron(req.getCron());
            pipelineSchedulingPropertiesDao.insert(pipelineSchedulingProperties);
//            pipelineSchedulingProperties.setStatus(PipelineSchedulingStatusEnum.READY.getCode());
        }

    }

    /**
     * 删除任务
     */
    public void removeTask(PipelineSchedulingReq req) throws SchedulerException {
        TriggerKey triggerKey = TriggerKey.triggerKey(req.getPipelineId(), TRIGGER_GROUP_NAME);
        scheduler.pauseTrigger(triggerKey);
        scheduler.unscheduleJob(triggerKey);
        scheduler.deleteJob(JobKey.jobKey(req.getPipelineId(), JOB_GROUP_NAME));
        log.info("任务 [{}] 已删除", req.getPipelineId());

        //数据删除
        QueryWrapper<PipelineSchedulingProperties> wrapper = new QueryWrapper<>();
        wrapper.eq("pipeline_id", req.getPipelineId());
        wrapper.eq("cron",  req.getCron());
        List<PipelineSchedulingProperties> list = pipelineSchedulingPropertiesDao.selectList(wrapper);

        if (!CollectionUtils.isEmpty(list)){
            List<String> idList = list.stream().map(PipelineSchedulingProperties::getId).toList();
            pipelineSchedulingPropertiesDao.deleteByIds(idList);
        }
    }

    /**
     * 更新任务
     */
    public void updateTask(PipelineSchedulingReq req) throws Exception {
        removeTask(req);
        addTask(req);
        log.info("任务 [{}] 已更新，新 cron: {}", req.getPipelineId(), req.getCron());
    }

    /**
     * 启动/重启任务
     */
    public void startTask(PipelineSchedulingReq req) throws SchedulerException {
        JobKey jobKey = JobKey.jobKey(req.getPipelineId(), JOB_GROUP_NAME);
        if (!scheduler.checkExists(jobKey)) {
            log.warn("任务 [{}] 不存在", req.getPipelineId());
            return;
        }

        if (scheduler.isShutdown()) {
            scheduler.start();
        }

        List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
        for (Trigger trigger : triggers) {
            if (trigger.getNextFireTime() == null) {
                scheduler.rescheduleJob(TriggerKey.triggerKey(req.getPipelineId(), TRIGGER_GROUP_NAME), trigger);
            }
        }

        log.info("任务 [{}] 已重启", req.getPipelineId());
    }
}
