package com.ruoyi.quartz.task;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUnit;
import com.google.common.collect.Lists;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.DateUtil;
import com.ruoyi.system.domain.form.MdForm;
import com.ruoyi.system.domain.form.MdFormExample;
import com.ruoyi.system.domain.form.MdFormRecord;
import com.ruoyi.system.domain.form.MdFormRecordExample;
import com.ruoyi.system.domain.form.enums.EnumFormType;
import com.ruoyi.system.domain.form.enums.EnumStartDateByQua;
import com.ruoyi.system.service.form.FormMsgManager;
import com.ruoyi.system.service.form.FormRecordManager;
import com.ruoyi.system.service.form.MdFormRecordService;
import com.ruoyi.system.service.form.MdFormService;
import com.ruoyi.system.service.system.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Author wp
 * @Description //凌晨 统一修改周期表单的当前周期，填报数据清空，并生成新的“表单填报数据”
 * @Date 9:39 2020/8/19
 * @Param
 * @return
 **/
@Component("formCycleTask")
@Slf4j
public class FormCycleTask {

    @Autowired
    private MdFormService formService;

    @Autowired
    private MdFormRecordService formRecordService;

    @Autowired
    private FormRecordManager recordManager;

    @Autowired
    private FormMsgManager formMsgManager;

    @Autowired
    private ISysUserService sysUserService;

    /**
     * @return void
     * @Author wp
     * @Description //企业填报定时任务【周期、临时、提醒】
     * @Date 13:44 2020/8/24
     * @Param []
     **/
    //@Scheduled(cron = "0 0 1 * * ? ")//凌晨1点执行
    public void jobTask() {

        job1();

        job2();

        job3();
    }


    private void job1() {

        System.out.println("-----开始修改周期性表单----");

        MdFormExample example = new MdFormExample();
        MdFormExample.Criteria c = example.createCriteria();
        c.andCollectModeEqualTo(EnumFormType.cycle.text);
        c.andPublishStatusEqualTo(1);
        c.andStatusEqualTo(1);

        String ww = DateUtil.getCycleNow("ww");//周
        String m = DateUtil.getCycleNow("m");//月
        String q = DateUtil.getCycleNow("q");//季度

        List<MdForm> list = formService.selectByExampleWithBLOBs(example);

        if (CollectionUtils.isEmpty(list)) {
            return;
        }

        for (MdForm mdForm : list) {

            String whatNow = "";

            if ("ww".equals(mdForm.getCycleType())) whatNow = ww;
            if ("m".equals(mdForm.getCycleType())) whatNow = m;
            if ("q".equals(mdForm.getCycleType())) whatNow = q;

            //周期不变
            if (whatNow.equals(mdForm.getCycleNow())) {
                continue;
            }
            String old_cycle = mdForm.getCycleNow();

            //如果是新的周期，那么就修改当前周期，清空填报数量，并且生成新的表单填报数据。
            mdForm.setCycleNow(whatNow);
            mdForm.setRecordNum(0);//清空
            formService.updateByPrimaryKeySelective(mdForm);

            //获取用户id
            List<String> ids = userList(mdForm);
            final String _commit_cycle = whatNow;

            Lists.partition(ids, 500).forEach(_list -> {

                //查询历史数据
                MdFormRecordExample formExample = new MdFormRecordExample();
                formExample.createCriteria().andFormIdEqualTo(mdForm.getId())
                        .andCommitCycleEqualTo(old_cycle)
                        .andOwnUserIn(_list);

                List<MdFormRecord> records = formRecordService.selectByExampleWithBLOBs(formExample);
                records = CollectionUtils.isEmpty(records) ? Collections.emptyList() : records;

                Map<String, MdFormRecord> _map = records.stream().collect(Collectors.toMap(MdFormRecord::getOwnUser, Function.identity()));

                recordManager.insertBatch(_list.stream().map(_id -> {
                    MdFormRecord _r = _map.getOrDefault(_id, new MdFormRecord());

                    if (StringUtils.isBlank(_r.getId())) {
                        _r.setFormId(mdForm.getId());
                        _r.setStatus(1);
                        _r.setOwnUser(_id);
                        _r.setCommitCycle(mdForm.getCycleNow());
                    }

                    _r.setId("record-" + UUID.randomUUID().toString());
                    _r.setCommitStatus(0);
                    _r.setCommitCycle(_commit_cycle);

                    //不需要默认
                    if (mdForm.getCycleDef() == null || mdForm.getCycleDef() == 0) {
                        _r.setRecords("");
                        _r.setOwnUser("");
                        _r.setOwnDept("");
                    }

                    return _r;
                }).collect(Collectors.toList()));
            });
        }
        System.out.println("-----开始修改周期性表单-结束----");
    }

    private void job2() {

        System.out.println("*******开始修改临时表单-开始*****");
        //以下任务应该剥离出来，用异步做。
        MdFormExample example2 = new MdFormExample();
        MdFormExample.Criteria c2 = example2.createCriteria();
        c2.andPublishStatusEqualTo(1);
        c2.andStatusEqualTo(1);
        c2.andCollectModeEqualTo(EnumFormType.fix.text); //不可以覆盖吗？
        List<MdForm> fixList = formService.selectByExample(example2);
        long now = System.currentTimeMillis();

        if (CollectionUtil.isNotEmpty(fixList)) {
            fixList.forEach(e -> {
                if (e.getFixEnd() != null) {
                    if (now > e.getFixEnd()) {
                        MdForm mdForm = new MdForm();
                        mdForm.setPublishStatus(2);
                        mdForm.setId(e.getId());
                        formService.updateByPrimaryKeySelective(mdForm);
                    }
                }
            });
        }
        System.out.println("*******开始修改临时表单-结束*****");
    }


    public List<String> userList(MdForm mdForm) {
        if (mdForm.getPublishMode() == null) {
            return Collections.emptyList();
        }
        List<String> ids = new ArrayList<>();

        //发布方式 0-部分 1-全部
        if (1 == mdForm.getPublishMode()) {
            //查询出全部员工

            SysUser userParam = new SysUser();
            userParam.setStatus("0");

            List<SysUser> users = sysUserService.selectUserList(userParam);

            for (SysUser user : users) {
                ids.add(user.getUserId());
            }

        } else {
            if (StringUtils.isNotEmpty(mdForm.getPublishUser())) {
                ids.addAll(Arrays.asList(mdForm.getPublishUser().split(",")));
            }
        }

        return ids;
    }

    private void job3() {
        System.out.println("#########提醒-开始#####");
        MdFormExample example3 = new MdFormExample();
        MdFormExample.Criteria c3 = example3.createCriteria();
        c3.andPublishStatusEqualTo(1);
        c3.andStatusEqualTo(1);

        List<MdForm> allList = formService.selectByExample(example3);
        if (!CollectionUtils.isEmpty(allList)) {

            for (MdForm form : allList) {
                Boolean b;
                //临时
                if (EnumFormType.fix.text.equals(form.getCollectMode())) {
                    //当前时间字符串，格式：yyyy-MM-dd
                    //endTime  20200820 23:59:59
                    String nowTime2 = cn.hutool.core.date.DateUtil.today();
                    String stampToDate = DateUtil.stampToDate(form.getFixEnd(), "");//截止时间
                    Date date1 = cn.hutool.core.date.DateUtil.parse(nowTime2);
                    Date date2 = cn.hutool.core.date.DateUtil.parse(stampToDate);
                    //此处是截至时间和当前时间的相差时间。如：截至8.26号，今天8.24，那么就是2天。今天是不提醒
                    long betweenDay = cn.hutool.core.date.DateUtil.between(date2, date1, DateUnit.DAY);
                    int mindDay = form.getMindTime();//提前提醒时间。
                    //如果提前两天提醒，截至是8.26，那么就是8.25号凌晨提醒。
                    b = mindDay == betweenDay;
                } else {//周期
                    b = judgeTime(form);
                }
                if (b) {
                    formMsgManager.send4Mind(form.getId(), null, false);
                }
            }
            System.out.println("#########提醒-结束#####");
        }
    }

    //判断今天和本维度最后一天的时间差。以下的getMindTime，得根据周期维度来设置对应得持续天数
    //比如，周，那么持续天数就在七天之内。
    private Boolean judgeTime(MdForm form) {
        Boolean flag = false;
        int nowDay = 0;
        switch (form.getCycleType()) {
            case "ww":
                nowDay = DateUtil.getWeek();//今天星期几？
                //flag = (now+form.getMindTime())==8; //比如：今天星期二，提前5天提醒，就是周三凌晨提醒，3+5=8。今天不提醒。
                break;
            case "m":
                LocalDate localDate = LocalDate.now();
                nowDay = localDate.getDayOfMonth();//今天是当月第几天
                //int days = localDate.lengthOfMonth(); //本月多少天
                //int mindTime = form.getMindTime();//提前多少天提醒
                break;
            default:
                nowDay = (int) getDayQ() + 1;//今天是此季度的第nowQ天。
                break;
        }
        if ((form.getCycleLast() - form.getMindTime()) == nowDay) {//如果持续天数为20天，提前5天提醒，那就是15号提醒。15+5=20提醒
            flag = true;
        }
        return flag;
    }

    //获取季度开头到现在的天数差
    private long getDayQ() {
        //当前季度
        int nowQ = DateUtil.getCurrentQuarter();
        //月 日
        String startDay = EnumStartDateByQua.getValue(nowQ);
        //年
        LocalDate localDate = LocalDate.now();
        //季度开始时间
        String startDate = localDate.getYear() + startDay;
        Date date1 = cn.hutool.core.date.DateUtil.parse(startDate);
        long betweenDay = cn.hutool.core.date.DateUtil.between(date1, new Date(), DateUnit.DAY);
        return betweenDay;
    }
}
