package org.wcs.plugin.quartz;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Component
@RequiredArgsConstructor
public class QuartzComponent {

    private static final String BASE_PACKAGE = "org.wcs.quartzJob";

    private static List<QuartzJobBean> quartzJobBeans;

    private final Scheduler scheduler;

    /**
     * 扫描定时任务类
     */
    public void scanQuartzJob() {
        quartzJobBeans = new ArrayList<>();
        ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
        try {
            String RESOURCE_PATTERN = "/**/*.class";
            String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
                    ClassUtils.convertClassNameToResourcePath(BASE_PACKAGE) + RESOURCE_PATTERN;
            Resource[] resources = resourcePatternResolver.getResources(pattern);
            MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(resourcePatternResolver);
            for (Resource resource : resources) {
                MetadataReader reader = readerFactory.getMetadataReader(resource);
                //扫描到的class
                String classname = reader.getClassMetadata().getClassName();
                Class<?> clazz = Class.forName(classname);
                if (Job.class.isAssignableFrom(clazz)) {
                    log.info("扫描到定时Job类：{}", classname);
                    QuartzJobBean quartzJobBean = new QuartzJobBean();
                    quartzJobBean.setJobName(clazz.getSimpleName());
                    quartzJobBean.setJobClass(clazz.asSubclass(Job.class));
                    quartzJobBeans.add(quartzJobBean);
                }
            }
        } catch (IOException | ClassNotFoundException e) {
            log.error("加载定时任务类失败", e);
        }
    }

    /**
     * 获取定时任务列表
     * @return 定时任务列表
     */
    public List<QuartzJobBean> getQuartzJobBeans() {
        return quartzJobBeans;
    }

    /**
     * 创建定时任务
     * @param quartzJobBean 定时任务
     * @param cron cron 表达式
     * @return true:创建成功 false:创建失败
     */
    public boolean createQuartzJob(QuartzJobBean quartzJobBean, String cron) {
        JobDetail jobDetail = JobBuilder.newJob(quartzJobBean.getJobClass())
                .withIdentity(quartzJobBean.getJobName())
                .build();
        Trigger trigger = TriggerBuilder.newTrigger()
                .forJob(jobDetail)
                .withSchedule(CronScheduleBuilder.cronSchedule(cron))
                .withIdentity(quartzJobBean.getJobName() + "_Trigger")
                .build();
        try {
            scheduler.scheduleJob(jobDetail, trigger);
            return true;
        } catch (SchedulerException e) {
            log.error("创建定时任务类失败", e);
            return false;
        }
    }

    /**
     * 暂停定时任务
     * @param jobName 任务名
     * @return 暂停结果
     */
    public boolean stopQuartzJob(String jobName) {
        JobKey  jobKey = JobKey.jobKey(jobName);
        try {
            scheduler.pauseJob(jobKey);
            return true;
        } catch (SchedulerException e) {
            log.error("停止定时任务类失败", e);
            return false;
        }
    }

    /**
     * 恢复定时任务
     * @param jobName 任务名
     * @return 恢复结果
     */
    public boolean resumeQuartzJob(String jobName) {
        JobKey  jobKey = JobKey.jobKey(jobName);
        try {
            scheduler.resumeJob(jobKey);
            return true;
        } catch (SchedulerException e) {
            log.error("恢复定时任务类失败", e);
            return false;
        }
    }

    /**
     * 删除定时任务
     * @param jobName 删除任务名
     * @return 删除结果
     */
    public boolean deleteQuartzJob(String jobName) {
        JobKey  jobKey = JobKey.jobKey(jobName);
        try {
            scheduler.deleteJob(jobKey);
            return true;
        } catch (SchedulerException e) {
            log.error("删除定时任务类失败", e);
            return false;
        }
    }



}
