package net.northking.cctp.executePlan.quartz;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.extra.spring.SpringUtil;
import net.northking.cctp.executePlan.api.service.AtuPlanInfoApiService;
import net.northking.cctp.executePlan.constants.QuartzConstant;
import net.northking.cctp.executePlan.db.entity.AtuPlanInfo;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;

/**
 * <p>Title: AbstractQuartzJob</p>
 * <p>Description: </p>
 *
 * @Author chenjianfeng
 * @Version V1.0
 * @Date 2022/12/29
 * <p>Copyright (c) 京北方信息技术股份有限公司 Corporation 2022 . All rights reserved.</p>
 */

public abstract class AbstractQuartzJob implements Job {

    protected static final Logger log = LoggerFactory.getLogger(AbstractQuartzJob.class);

    /**
     * 线程本地变量
     */
    private static final ThreadLocal<Date> THREAD_LOCAL = new ThreadLocal<>();

    @Override
    public void execute(JobExecutionContext context)
    {
        AtuPlanInfo planInfo = new AtuPlanInfo();
        BeanUtil.copyProperties(context.getMergedJobDataMap().get(QuartzConstant.PLAN_TASK_PROPERTIES), planInfo);
        try
        {
            before(context, planInfo);
            if (planInfo != null)
            {
                doExecute(context, planInfo);
            }
            after(context, planInfo, null);
        }
        catch (Exception e)
        {
            log.error("任务执行异常  - ：", e);
            after(context, planInfo, e);
        }
    }

    /**
     * 执行前
     *
     * @param context 工作执行上下文对象
     * @param planInfo 调度计划
     */
    protected void before(JobExecutionContext context, AtuPlanInfo planInfo)
    {
        log.info("调度计划[{}-{}]被触发调用",planInfo.getId(), planInfo.getPlanName());
        THREAD_LOCAL.set(new Date());
    }

    /**
     * 任务派发后
     * @param context 工作执行上下文对象
     * @param planInfo 调度计划
     * @param e 异常
     */
    protected void after(JobExecutionContext context, AtuPlanInfo planInfo, Exception e)
    {
        Date startTime = THREAD_LOCAL.get();
        long runMs = System.currentTimeMillis() - startTime.getTime();
        if(e!=null){
            log.info("调度计划[{}-{}]派发失败,派发共耗时:{}秒", planInfo.getId(), planInfo.getPlanName(), runMs/1000.0);
            log.warn("调度计划派发失败原因",e);
        }else{
            log.info("调度计划[{}-{}]已成功派发,耗时:{}秒", planInfo.getId(), planInfo.getPlanName(),runMs/1000.0);
        }
        log.trace("计划内容:{}", planInfo);
        THREAD_LOCAL.remove();

        // 修改下一次执行时间
        log.info("更新下一次执行时间");
        planInfo.setLastExecTime(new Date());
        SpringUtil.getBean(AtuPlanInfoApiService.class).updatePlanNextRunTime(planInfo);
    }

    /**
     * 执行方法，由子类重载
     *
     * @param context 工作执行上下文对象
     * @param planInfo 系统计划任务
     * @throws Exception 执行过程中的异常
     */
    protected abstract void doExecute(JobExecutionContext context, AtuPlanInfo planInfo) throws Exception;
}
