package cn.lihongjie.coal.cronJob.service;

import cn.lihongjie.coal.common.Ctx;
import cn.lihongjie.coal.cronJob.dto.CronJobDto;
import cn.lihongjie.coal.cronJob.entity.CronJobEntity;
import cn.lihongjie.coal.cronJobLog.entity.CronJobLogEntity;
import cn.lihongjie.coal.cronJobLog.service.CronJobLogService;
import cn.lihongjie.coal.script.dto.ScriptExecResultDto;
import cn.lihongjie.coal.script.service.ScriptService;

import com.fasterxml.jackson.databind.ObjectMapper;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.context.ConfigurableApplicationContext;

import java.time.LocalDateTime;
import java.util.*;

@Slf4j
public class CronScriptJob implements Job {
    @SneakyThrows
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {

        LocalDateTime start = LocalDateTime.now();

        ConfigurableApplicationContext applicationContext = Ctx.getContext();

        ScriptService scriptService = applicationContext.getBean(ScriptService.class);

        CronJobService cronJobService = applicationContext.getBean(CronJobService.class);
        ObjectMapper objectMapper = applicationContext.getBean(ObjectMapper.class);
        CronJobLogService cronJobLogService = applicationContext.getBean(CronJobLogService.class);

        Object cronJobId = context.getMergedJobDataMap().get("id");
        String params = ObjectUtils.defaultIfNull(context.getMergedJobDataMap().get("params"), "{}") + "";

        CronJobDto cronJobDto = cronJobService.getById(cronJobId + "");

        ScriptExecResultDto resultDto = new ScriptExecResultDto();
        resultDto.setParams(objectMapper.readTree(params));
        resultDto.setId(cronJobDto.getScript().getId());
        Exception ex = null;
        try {

            scriptService.exec(resultDto);
        } catch (Exception e) {
            log.warn("执行定时任务失败 {} {} {} {}",cronJobDto.getId(), cronJobDto.getName(), cronJobDto.getCron(), cronJobDto.getScript().getName(),  e);

            ex = e;
        }


        LocalDateTime end = LocalDateTime.now();


        CronJobLogEntity jobLog = new CronJobLogEntity();
        CronJobEntity entity = new CronJobEntity();
        entity.setId(cronJobDto.getId());

        jobLog.setCronJob(entity);

        jobLog.setParams(params);
        jobLog.setStartTime(start);
        jobLog.setExecStatus(ex !=null || resultDto.getStackTrace() != null ? "1" : "0");

        jobLog.setEndTime(end);
        jobLog.setStackTrace(ex == null ? resultDto.getStackTrace() : ExceptionUtils.getStackTrace(ex));
        jobLog.setLogs(StringUtils.substring(String.join("\n", resultDto.getLogs()), 0, 1024));

        cronJobLogService.save(jobLog);
    }
}
