package com.qmth.sop.task.job.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qmth.sop.business.cache.CommonCacheService;
import com.qmth.sop.business.entity.SysConfig;
import com.qmth.sop.business.entity.SysUser;
import com.qmth.sop.business.entity.TBTask;
import com.qmth.sop.business.entity.TSJobRemind;
import com.qmth.sop.business.service.*;
import com.qmth.sop.business.templete.execute.AsyncFxxkCrmSyncService;
import com.qmth.sop.business.templete.execute.AsyncRtzfUserPushService;
import com.qmth.sop.business.templete.execute.AsyncRtzfUserUpdateBatchService;
import com.qmth.sop.common.contant.SystemConstant;
import com.qmth.sop.common.enums.*;
import com.qmth.sop.task.job.RemindTaskJob;
import com.qmth.sop.task.job.service.JobService;
import com.qmth.sop.task.service.QuartzService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.time.Duration;
import java.util.*;

/**
 * @Description: job service impl
 * @Param:
 * @return:
 * @Author: wangliang
 * @Date: 2021/3/31
 */
@Service
public class JobServiceImpl implements JobService {

    private final static Logger log = LoggerFactory.getLogger(JobServiceImpl.class);

    @Resource
    QuartzService quartzService;

    @Resource
    TSJobRemindService tsJobRemindService;

    @Resource
    CommonCacheService commonCacheService;

    @Resource
    SequenceService sequenceService;

    @Resource
    AsyncFxxkCrmSyncService asyncFxxkCrmSyncService;

    @Resource
    TBTaskService tbTaskService;

    @Resource
    SysUserService sysUserService;

    @Resource
    TBDingService tbDingService;

    @Resource
    AsyncRtzfUserPushService asyncRtzfUserPushService;

    @Resource
    AsyncRtzfUserUpdateBatchService asyncRtzfUserUpdateBatchService;

    /**
     * 流程任务提醒task
     */
    @Override
    @Transactional
    public void flowTaskRemindTask() {
        log.info("flowTaskRemindTask is come in");
        //        List<TSJobRemind> tsJobRemindList = tsJobRemindService.list(new QueryWrapper<TSJobRemind>().lambda().isNull(TSJobRemind::getExecTime).last(" limit 0,100 "));
        SysConfig sysConfig = commonCacheService.addSysConfigCache(SystemConstant.REMIND_JOB_DB_LIMIT);
        Optional.ofNullable(sysConfig).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("任务提醒查询条数未设置"));
        List<TSJobRemind> tsJobRemindList = tsJobRemindService.list(
                new QueryWrapper<TSJobRemind>().lambda().isNull(TSJobRemind::getExecTime).last(" " + sysConfig.getConfigValue() + " "));
        if (!CollectionUtils.isEmpty(tsJobRemindList)) {
            List<TSJobRemind> tsJobRemindUpdateList = new ArrayList<>(tsJobRemindList.size());
            for (TSJobRemind t : tsJobRemindList) {
                if (Objects.nonNull(t.getEnable()) && t.getEnable()) {//新建定时任务
                    if (t.getType() == JobQuartzTypeEnum.FLOW) {//流程
                        switch (t.getRemindType()) {
                        case BEFORE://提前提醒
                            SysConfig sysConfigBefore = commonCacheService.addSysConfigCache(SystemConstant.FLOW_JOB_BEFORE_TIME);
                            Optional.ofNullable(sysConfigBefore).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程提前提醒任务时间未设置"));
                            Long execTime = SystemConstant.processMiniuteMinus(t.getCreateTime(), Duration.ofMinutes(Long.parseLong(sysConfigBefore.getConfigValue())));
                            if (Objects.nonNull(execTime) && execTime.longValue() > System.currentTimeMillis()) {
                                t.setExecTime(execTime);
                                this.setJobTime(execTime, t.getId().toString(), t, RemindTaskJob.class, JobEnum.REMIND_QUARTZ_JOB_GROUP);
                                tsJobRemindUpdateList.add(t);
                            }
                            break;
                        case AFTER://超时提醒
                            SysConfig sysConfigAfter = commonCacheService.addSysConfigCache(SystemConstant.FLOW_JOB_AFTER_TIME);
                            Optional.ofNullable(sysConfigAfter).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程超时提醒任务时间未设置"));
                            execTime = SystemConstant.processMiniutePlus(t.getCreateTime(), Duration.ofMinutes(Long.parseLong(sysConfigAfter.getConfigValue())));
                            if (Objects.nonNull(execTime) && execTime.longValue() > System.currentTimeMillis()) {
                                t.setExecTime(execTime);
                                this.setJobTime(execTime, t.getId().toString(), t, RemindTaskJob.class, JobEnum.REMIND_QUARTZ_JOB_GROUP);
                                tsJobRemindUpdateList.add(t);
                            }
                            break;
                        default:
                            break;
                        }
                    } else if (t.getType() == JobQuartzTypeEnum.FLOW) {//通告
                        switch (t.getRemindType()) {
                        case AFTER://超时提醒
                            SysConfig sysConfigAfter = commonCacheService.addSysConfigCache(SystemConstant.NOTICE_JOB_AFTER_TIME);
                            Optional.ofNullable(sysConfigAfter).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("公告超时提醒任务时间未设置"));
                            Long execTime = SystemConstant.processMiniutePlus(t.getCreateTime(), Duration.ofMinutes(Long.parseLong(sysConfigAfter.getConfigValue())));
                            if (Objects.nonNull(execTime) && execTime.longValue() > System.currentTimeMillis()) {
                                t.setExecTime(execTime);
                                this.setJobTime(execTime, t.getId().toString(), t, RemindTaskJob.class, JobEnum.REMIND_QUARTZ_JOB_GROUP);
                                tsJobRemindUpdateList.add(t);
                            }
                            break;
                        default:
                            break;
                        }
                    }
                }
            }
            if (!CollectionUtils.isEmpty(tsJobRemindUpdateList)) {
                tsJobRemindService.saveOrUpdateBatch(tsJobRemindUpdateList);
            }
        }

        List<TSJobRemind> tsJobRemindFalseList = tsJobRemindService.list(
                new QueryWrapper<TSJobRemind>().lambda().eq(TSJobRemind::getEnable, false).last(" " + sysConfig.getConfigValue() + " "));
        if (!CollectionUtils.isEmpty(tsJobRemindFalseList)) {
            List<Long> tsJobRemindFalseIdList = new ArrayList<>(tsJobRemindFalseList.size());
            for (TSJobRemind t : tsJobRemindFalseList) {
                //禁用需删除定时任务
                quartzService.deleteJob(t.getObjId().toString(), JobEnum.REMIND_QUARTZ_JOB_GROUP.name());
                tsJobRemindFalseIdList.add(t.getId());
            }
            if (!CollectionUtils.isEmpty(tsJobRemindFalseIdList)) {
                tsJobRemindService.removeByIds(tsJobRemindFalseIdList);
            }
        }
    }

    /**
     * 设置定时任务时间
     *
     * @param finishTime
     * @param jobName
     * @param o
     * @param cls
     * @param jobEnum
     */
    @Override
    public void setJobTime(Long finishTime, String jobName, Object o, Class cls, JobEnum jobEnum) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(finishTime);
        //        calendar.add(Calendar.SECOND, 30);
        if (calendar.getTime().getTime() > System.currentTimeMillis()) {
            int year = calendar.get(Calendar.YEAR);//获取年份
            int month = calendar.get(Calendar.MONTH) + 1;//获取月份
            int day = calendar.get(Calendar.DATE);//获取日
            int hour = calendar.get(Calendar.HOUR_OF_DAY);//小时
            int minute = calendar.get(Calendar.MINUTE);//分
            int second = calendar.get(Calendar.SECOND);//秒
            String cron = second + " " + minute + " " + hour + " " + day + " " + month + " ? " + year;
            log.info("cron:{}", cron);
            //执行一次性延时任务
            Map mapJob = new HashMap();
            mapJob.put(SystemConstant.NAME, jobName);
            mapJob.put(SystemConstant.JOB_DATA, o);
            quartzService.addJob(cls, jobName, jobEnum.name(), cron, mapJob);
        }
    }

    /**
     * 序列重置
     */
    @Override
    public void sequenceReset() {
        sequenceService.sequenceReset();
    }

    @Override
    public void fxxkCrmSync() throws Exception {
        SysUser sysUser = sysUserService.getOne(
                new QueryWrapper<SysUser>().lambda().eq(SysUser::getLoginName, "sysadmin"));
        Map<String, Object> map = new HashMap<>();
        List<TBTask> tbTaskList = tbTaskService.list(
                new QueryWrapper<TBTask>().lambda().eq(TBTask::getType, TaskTypeEnum.CRM_SYNC));
        TBTask tbTask;
        if (!CollectionUtils.isEmpty(tbTaskList)) {
            if (tbTaskList.size() > 1) {
                throw ExceptionResultEnum.ERROR.exception(String.format("存在多条类型为[%s]的任务", TaskTypeEnum.CRM_SYNC.getTitle()));
            }
            tbTask = tbTaskList.get(0);
            tbTask.setStatus(TaskStatusEnum.RUNNING);
            tbTaskService.updateById(tbTask);
        } else {
            if (Objects.isNull(sysUser)) {
                throw ExceptionResultEnum.ERROR.exception("缺少系统管理员");
            }
            tbTask = new TBTask(TaskTypeEnum.CRM_SYNC, TaskStatusEnum.RUNNING, sysUser.getId());
            tbTaskService.save(tbTask);
        }
        map.put(SystemConstant.TASK, tbTask);
        map.put(SystemConstant.USER, sysUser);
        asyncFxxkCrmSyncService.syncData(map);
    }

    @Override
    public void rtzfUserPush() throws Exception {
        SysUser sysUser = sysUserService.getOne(
                new QueryWrapper<SysUser>().lambda().eq(SysUser::getLoginName, "sysadmin"));
        Map<String, Object> map = new HashMap<>();
        List<TBTask> tbTaskList = tbTaskService.list(
                new QueryWrapper<TBTask>().lambda().eq(TBTask::getType, TaskTypeEnum.RTZF_USER_PUSH_SYNC));
        TBTask tbTask;
        if (!CollectionUtils.isEmpty(tbTaskList)) {
            if (tbTaskList.size() > 1) {
                throw ExceptionResultEnum.ERROR.exception(String.format("存在多条类型为[%s]的任务", TaskTypeEnum.RTZF_USER_PUSH_SYNC.getTitle()));
            }
            tbTask = tbTaskList.get(0);
            tbTask.setStatus(TaskStatusEnum.RUNNING);
            tbTaskService.updateById(tbTask);
        } else {
            if (Objects.isNull(sysUser)) {
                throw ExceptionResultEnum.ERROR.exception("缺少系统管理员");
            }
            tbTask = new TBTask(TaskTypeEnum.RTZF_USER_PUSH_SYNC, TaskStatusEnum.RUNNING, sysUser.getId());
            tbTaskService.save(tbTask);
        }
        map.put(SystemConstant.TASK, tbTask);
        map.put(SystemConstant.USER, sysUser);
        asyncRtzfUserPushService.syncData(map);
    }

    @Override
    public void rtzfUserUpdate() throws Exception {
        SysUser sysUser = sysUserService.getOne(
                new QueryWrapper<SysUser>().lambda().eq(SysUser::getLoginName, "sysadmin"));
        Map<String, Object> map = new HashMap<>();
        List<TBTask> tbTaskList = tbTaskService.list(
                new QueryWrapper<TBTask>().lambda().eq(TBTask::getType, TaskTypeEnum.RTZF_USER_UPDATE_SYNC));
        TBTask tbTask;
        if (!CollectionUtils.isEmpty(tbTaskList)) {
            if (tbTaskList.size() > 1) {
                throw ExceptionResultEnum.ERROR.exception(String.format("存在多条类型为[%s]的任务", TaskTypeEnum.RTZF_USER_UPDATE_SYNC.getTitle()));
            }
            tbTask = tbTaskList.get(0);
            tbTask.setStatus(TaskStatusEnum.RUNNING);
            tbTaskService.updateById(tbTask);
        } else {
            if (Objects.isNull(sysUser)) {
                throw ExceptionResultEnum.ERROR.exception("缺少系统管理员");
            }
            tbTask = new TBTask(TaskTypeEnum.RTZF_USER_UPDATE_SYNC, TaskStatusEnum.RUNNING, sysUser.getId());
            tbTaskService.save(tbTask);
        }
        map.put(SystemConstant.TASK, tbTask);
        map.put(SystemConstant.USER, sysUser);
        asyncRtzfUserUpdateBatchService.syncData(map);
    }

    @Override
    public void autoAddDingRecord() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(System.currentTimeMillis());
        String signYear = calendar.get(Calendar.YEAR) + "年";
        String signDay = calendar.get(Calendar.MONTH) + 1 + "月" + calendar.get(Calendar.DATE) + "日";
        tbDingService.autoAddDingRecord(signYear, signDay);
    }
}
