package com.dxhy.core.job.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dxhy.common.constant.ConfigureConstant;
import com.dxhy.common.constant.DbConstant;
import com.dxhy.common.datasource.config.DynamicContextHolder;
import com.dxhy.common.utils.Constant;
import com.dxhy.common.utils.DateUtils;
import com.dxhy.common.utils.PageUtils;
import com.dxhy.common.utils.Query;
import com.dxhy.core.job.dao.ScheduleJobDao;
import com.dxhy.core.job.dao.ScheduleJobLogDao;
import com.dxhy.core.job.entity.ScheduleJobEntity;
import com.dxhy.core.job.entity.ScheduleJobLogEntity;
import com.dxhy.core.job.service.ScheduleJobService;
import com.dxhy.core.job.thread.DoScheJobByBeanNameMethodHandle;
import com.dxhy.core.job.utils.ScheduleUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.quartz.CronTrigger;
import org.quartz.Scheduler;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author user
 */
@Service("scheduleJobService")
@Slf4j

public class ScheduleJobServiceImpl extends ServiceImpl<ScheduleJobDao, ScheduleJobEntity>
    implements ScheduleJobService {
    @Value("${schedule.open}")
    private Boolean isScheduleOpen;
    @Resource
    private Scheduler scheduler;

    @Resource
    private ScheduleJobLogDao scheduleJobLogDao;

    @Value("${schedule.scheduleRestoreTime:300}")
    private int scheduleRestoreTime;

    /**
     * 项目启动时，初始化定时器
     */
    @PostConstruct
    public void init() {
        // 判断是否要开启定时器功能
        if (!isScheduleOpen) {
            return;
        }
        List<ScheduleJobEntity> scheduleJobList = this.listScheduleJobL();
        DynamicContextHolder.push(DbConstant.BASICS_WRITE);
        for (ScheduleJobEntity scheduleJob : scheduleJobList) {
            CronTrigger cronTrigger = ScheduleUtils.getCronTrigger(scheduler, scheduleJob.getJobId());
            // 如果不存在，则创建
            if (cronTrigger == null) {
                ScheduleUtils.createScheduleJob(scheduler, scheduleJob);
            } else {
                ScheduleUtils.updateScheduleJob(scheduler, scheduleJob);
            }
        }
    }

    public List<ScheduleJobEntity> listScheduleJobL() {
        DynamicContextHolder.push(DbConstant.BASICS_READ);
        return baseMapper.selectList(null);
    }

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        DynamicContextHolder.push(DbConstant.BASICS_READ);
        //支持，分开。现支持两个关键字
        String beanName = (String)params.get("beanName");
        beanName = StringUtils.isBlank(beanName)?"":beanName;

        String[] splitStr = beanName.replace("，", ",").split(",");

        String key1 = "";
        String key2 = "";
        if(splitStr.length==1){
            key1 = splitStr[0];
        }
        if(splitStr.length>=2){
            key1 = splitStr[0];
            key2 = splitStr[1];
        }

        QueryWrapper<ScheduleJobEntity> queryWrapper = new QueryWrapper<>();

        if(StringUtils.isNotBlank(key1)){
            String finalKey1 = key1;
            queryWrapper.and(wrapper->wrapper.like(StringUtils.isNotBlank(finalKey1), "bean_name", finalKey1).
                    or().
                    like( StringUtils.isNotBlank(finalKey1), "method_name", finalKey1).
                    or().
                    like( StringUtils.isNotBlank(finalKey1), "remark", finalKey1)
            );
        }
        if(StringUtils.isNotBlank(key2)){
            String finalKey2 = key2;
            queryWrapper.and(wrapper->wrapper.like(StringUtils.isNotBlank(finalKey2), "bean_name", finalKey2).
                    or().
                    like( StringUtils.isNotBlank(finalKey2), "method_name", finalKey2).
                    or().
                    like( StringUtils.isNotBlank(finalKey2), "remark", finalKey2)
            );
        }

        ;
        //类名，方法名，备注名都可查
        IPage<ScheduleJobEntity> page = this.page(new Query<ScheduleJobEntity>().getPage(params),
                queryWrapper
        );

        return new PageUtils(page);
    }

    public static void main(String[] args) {
        String a = "你好";
        String[] split = a.split(",");
        System.out.println(split.length);

    }

    @Override
    public void saveJob(ScheduleJobEntity scheduleJob) {
        DynamicContextHolder.push(DbConstant.BASICS_WRITE);
        this.insertJob(scheduleJob);
        ScheduleUtils.createScheduleJob(scheduler, scheduleJob);
    }

    @Transactional(rollbackFor = Exception.class)
    public void insertJob(ScheduleJobEntity scheduleJob) {
        scheduleJob.setCreateTime(new Date());
        scheduleJob.setStatus(Constant.ScheduleStatus.NORMAL.getValue());
        this.save(scheduleJob);
    }

    @Override
    public void update(ScheduleJobEntity scheduleJob) {
        DynamicContextHolder.push(DbConstant.BASICS_WRITE);
        ScheduleUtils.updateScheduleJob(scheduler, scheduleJob);
        this.updateJob(scheduleJob);
    }

    @Transactional(rollbackFor = Exception.class)
    public void updateJob(ScheduleJobEntity scheduleJob) {
        baseMapper.updateById(scheduleJob);
    }

    @Override

    public void deleteBatch(Long jobId) {
        DynamicContextHolder.push(DbConstant.BASICS_WRITE);
        ScheduleUtils.deleteScheduleJob(scheduler, jobId);
        // 删除数据
        this.deleteById(jobId);
    }

    @Transactional(rollbackFor = Exception.class)
    public void deleteById(Long jobId) {
        baseMapper.deleteById(jobId);
    }

    @Override
    public int updateBatch(Long jobId, int status) {
        DynamicContextHolder.push(DbConstant.BASICS_WRITE);

        return this.updateJob(jobId, status);
    }

    @Transactional(rollbackFor = Exception.class)
    public int updateJob(Long jobId, int status) {
        return baseMapper.updateBatch(status, jobId);
    }

    @Override
    public void run(Long jobId) {
        DynamicContextHolder.push(DbConstant.BASICS_WRITE);
        ScheduleUtils.run(scheduler, baseMapper.selectById(jobId));
    }

    @Override
    public void pause(Long jobId) {
        DynamicContextHolder.push(DbConstant.BASICS_WRITE);
        ScheduleUtils.pauseJob(scheduler, jobId);
        updateBatch(jobId, Constant.ScheduleStatus.PAUSE.getValue());
    }

    @Override
    public void resume(Long jobId) {
        DynamicContextHolder.push(DbConstant.BASICS_WRITE);
        ScheduleUtils.resumeJob(scheduler, jobId);
        updateBatch(jobId, Constant.ScheduleStatus.NORMAL.getValue());
    }

    @Override
    public ScheduleJobEntity queryById(Long jobId) {
        DynamicContextHolder.push(DbConstant.BASICS_READ);
        return baseMapper.selectById(jobId);
    }

    @Override
    public ScheduleJobEntity queryByBeanName(String beanName, String methodName) {
        QueryWrapper<ScheduleJobEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("bean_name", beanName);
        queryWrapper.eq("method_name", methodName);
        DynamicContextHolder.push(DbConstant.BASICS_READ);
        return baseMapper.selectOne(queryWrapper);
    }

    /**
     * @Description 通过定时任务类名和方法名执行任务。数组形式，顺序执行，每个任务之间间隔15秒
     * @param jobNames  beanName 名   methodName方法名
     * @Return org.springframework.http.ResponseEntity<?>
     * @Author wangruwei
     * @Date 2024/7/19 11:08
     **/
    @Override
    public void doScheJobByBeanNameMethods(List<Map<String, String>> jobNames) {
        //beanName
        //methodName
        DoScheJobByBeanNameMethodHandle eleKpPostInvoiceThread = new DoScheJobByBeanNameMethodHandle(baseMapper,this,jobNames);
        Thread thread = new Thread(eleKpPostInvoiceThread);
        thread.start();
    }

    @Override
    public void timedTaskRestore() {
        List<ScheduleJobEntity> scheduleJobList = baseMapper.selectList(new LambdaQueryWrapper<ScheduleJobEntity>()
                .eq(ScheduleJobEntity::getJobStatus, ConfigureConstant.STRING_1));
        if (!CollectionUtils.isEmpty(scheduleJobList)) {
            scheduleJobList.stream().forEach(e->{
                ScheduleJobLogEntity scheduleJobLogEntity = scheduleJobLogDao.selectOne(new LambdaQueryWrapper<ScheduleJobLogEntity>()
                        .eq(ScheduleJobLogEntity::getJobId, e.getJobId())
                        .orderByAsc(ScheduleJobLogEntity::getCreateTime)
                        .last("limit 1"));
                if(ObjectUtils.isNotEmpty(scheduleJobLogEntity)){
                    if (DateUtils.timeAdd(scheduleJobLogEntity.getCreateTime(), scheduleRestoreTime).compareTo(new Date()) < 0) {
                        log.info("jobId：{},该JOB长时间处于执行状态，重置为0");
                        e.setJobStatus(ConfigureConstant.STRING_0);
                        baseMapper.updateById(e);
                    }
                }
            });
        }
    }

}
