package org.nl.system.service.quartz.utils;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.nl.config.thread.ThreadPoolExecutorUtil;
import org.nl.common.utils.RedisUtils;
import org.nl.common.utils.ThrowableUtil;
import org.nl.config.SpringContextHolder;
import org.nl.system.service.quartz.ISysQuartzJobService;
import org.nl.system.service.quartz.dao.SysQuartzJob;
import org.nl.system.service.quartz.dao.SysQuartzLog;
import org.nl.system.service.quartz.dao.mapper.SysQuartzLogMapper;
import org.nl.system.service.quartz.impl.SysQuartzJobServiceImpl;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.quartz.QuartzJobBean;

import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @Author: /
 * @Description: 参考人人开源，https://gitee.com/renrenio/renren-security
 * @Date: 2022/12/19
 */
@Async
@SuppressWarnings({"unchecked", "all"})
@Slf4j
public class ExecutionJob extends QuartzJobBean {

    /**
     * 该处仅供参考
     */
    private final static ThreadPoolExecutor EXECUTOR = ThreadPoolExecutorUtil.getPoll();
    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        SysQuartzJob quartzJob = (SysQuartzJob) context.getMergedJobDataMap().get(SysQuartzJob.JOB_KEY);
        // 获取spring bean
        ISysQuartzJobService quartzJobService = SpringContextHolder.getBean(SysQuartzJobServiceImpl.class);
        SysQuartzLogMapper quartzLogMapper = SpringContextHolder.getBean(SysQuartzLogMapper.class);
        RedisUtils redisUtils = SpringContextHolder.getBean(RedisUtils.class);

        String uuid = quartzJob.getUuid();

        SysQuartzLog logDto = new SysQuartzLog();
        logDto.setLog_id(IdUtil.getSnowflake(1,1).nextIdStr());
        logDto.setJob_name(quartzJob.getJob_name());
        logDto.setBean_name(quartzJob.getBean_name());
        logDto.setMethod_name(quartzJob.getMethod_name());
        logDto.setParams(quartzJob.getParams());
        long startTime = System.currentTimeMillis();
        logDto.setCron_expression(quartzJob.getCron_expression());
        try {
            // 执行任务
            System.out.println("--------------------------------------------------------------");
            System.out.println("任务开始执行，任务名称：" + quartzJob.getJob_name());
            QuartzRunnable task = new QuartzRunnable(quartzJob.getBean_name(), quartzJob.getMethod_name(),
                    quartzJob.getParams());
            Future<?> future = EXECUTOR.submit(task);
            future.get();
            long times = System.currentTimeMillis() - startTime;
            logDto.setTime(times);
            if (StrUtil.isNotEmpty(uuid)) {
                redisUtils.set(uuid, true);
            }
            // 任务状态
            logDto.setIs_success(true);
            System.out.println("任务执行完毕，任务名称：" + quartzJob.getJob_name() + ", 执行时间：" + times + "毫秒");
            System.out.println("--------------------------------------------------------------");
            // 判断是否存在子任务
            if (StrUtil.isNotEmpty(quartzJob.getSub_task())) {
                String[] tasks = quartzJob.getSub_task().split("[,，]");
                // 执行子任务
                quartzJobService.executionSubJob(tasks);
            }
        } catch (Exception e) {
            if (StrUtil.isNotEmpty(uuid)) {
                redisUtils.set(uuid, false);
            }
            System.out.println("任务执行失败，任务名称：" + quartzJob.getJob_name());
            System.out.println("--------------------------------------------------------------");
            long times = System.currentTimeMillis() - startTime;
            logDto.setTime(times);
            // 任务状态 0：成功 1：失败
            logDto.setIs_success(false);
            logDto.setException_detail(ThrowableUtil.getStackTrace(e));
            // 任务如果失败了则暂停
            if (quartzJob.getPause_after_failure() != null && quartzJob.getPause_after_failure()) {
                quartzJob.setIs_pause(false);
                //更新状态
                quartzJobService.updateIsPause(quartzJob);
            }
            //异常时候打印日志
            log.info(logDto.toString());
            quartzLogMapper.insert(logDto);
        } finally {

        }
    }
}
