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

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.DbConstant;
import com.dxhy.common.datasource.config.DynamicContextHolder;
import com.dxhy.common.utils.Constant;
import com.dxhy.common.utils.PageUtils;
import com.dxhy.common.utils.Query;
import com.dxhy.core.job.dao.ScheduleJobDao;
import com.dxhy.core.job.entity.ScheduleJobEntity;
import com.dxhy.core.job.service.ScheduleJobService;
import com.dxhy.core.job.utils.ScheduleUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.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 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;

    /**
     * 项目启动时，初始化定时器
     */
    @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");

        //类名，方法名，备注名都可查
        IPage<ScheduleJobEntity> page = this.page(new Query<ScheduleJobEntity>().getPage(params),
            new QueryWrapper<ScheduleJobEntity>().like(StringUtils.isNotBlank(beanName), "bean_name", beanName).
                    or().
                    like( StringUtils.isNotBlank(beanName), "method_name", beanName).
                    or().
                    like( StringUtils.isNotBlank(beanName), "remark", beanName)

        );

        return new PageUtils(page);
    }

    @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);
    }

    /**
     * 获取用户扫描识别类型
     *
     * @param userId
     *            用户id
     * @return 识别类型
     */
    @Override
    public String getUserScanType(Long userId) {
        DynamicContextHolder.push(DbConstant.BASICS_READ);
        String scanType = baseMapper.getUserScanType(userId);
        if (StringUtils.isBlank(scanType)) {
            scanType = "0";
        }
        return scanType;
    }

    @Override
    public Map<String, String> getUserApplyKey(String loginName) {
        DynamicContextHolder.push(DbConstant.BASICS_READ);
        return baseMapper.getUserApplyKey(loginName);
    }

}
