package com.testor.module.duty.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.testor.biz.rule.service.SysRuleService;
import com.testor.biz.sys.org.model.domain.SysOrg;
import com.testor.biz.sys.org.service.SysOrgService;
import com.testor.biz.sys.post.model.domain.TSysPost;
import com.testor.biz.sys.post.service.TSysPostService;
import com.testor.biz.sys.user.model.domain.SysUser;
import com.testor.biz.sys.user.service.SysUserService;
import com.testor.common.constant.DefaultRule;
import com.testor.common.core.utils.DateUtils;
import com.testor.common.util.ExcelFillCellMergeStrategy;
import com.testor.common.util.excel.ExcelFillCellMergeStrategyUtils;
import com.testor.module.duty.dao.DutyDao;
import com.testor.module.duty.model.domain.*;
import com.testor.module.duty.model.dto.*;
import com.testor.module.duty.model.po.ExportDutyPo;
import com.testor.module.duty.model.po.ExportPo;
import com.testor.module.duty.service.*;
import com.testor.module.duty.util.PoiExcelUtils;
import com.testor.module.lease.controller.TLeaseBankController;
import com.testor.module.messageNotice.model.domain.TMsgNotice;
import com.testor.module.messageNotice.model.vo.MsgTemplateVO;
import com.testor.module.messageNotice.service.TMsgNoticeService;
import com.testor.module.sys.model.domian.NewSysOrg;
import com.testor.module.sys.model.vo.SysOrgVo;
import com.testor.module.sys.service.NewSysOrgService;
import com.tongtech.tfw.backend.common.biz.constants.BizConstants;
import com.tongtech.tfw.backend.common.biz.models.BaseResponse;
import com.tongtech.tfw.backend.common.biz.models.BizGeneralResponse;
import com.tongtech.tfw.backend.common.context.ContextUtils;
import com.tongtech.tfw.backend.common.exception.BusinessException;
import com.tongtech.tfw.backend.common.models.exceptions.ApiException;
import com.tongtech.tfw.backend.common.models.sys.UserInfo;
import com.tongtech.tfw.backend.core.helper.IdHelper;
import com.tongtech.tfw.backend.core.helper.ObjectHelper;
import com.tongtech.tfw.backend.core.helper.StringHelper;
import com.tongtech.tfw.backend.core.helper.TypeHelper;
import com.tongtech.tfw.backend.core.helper.bean.BeanHelper;
import com.tongtech.tfw.workflow.apis.definition.ProcessDefEnumCode;
import com.tongtech.tfw.workflow.apis.definition.controller.ProcessDefinitionController;
import com.tongtech.tfw.workflow.apis.definition.model.dto.ProcessDefStartParam;
import com.tongtech.tfw.workflow.service.TfwProcessInsService;
import com.tongtech.tfw.workflow.service.dto.ProcessInsStartParams;
import com.tongtech.tfw.workflow.service.dto.ProcessInsStartResult;
import groovy.util.logging.Slf4j;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collector;
import java.util.stream.Collectors;

@Service
@Slf4j
public class DutyServiceImpl extends ServiceImpl<DutyDao, TSysDuty> implements DutyService {
    @Autowired
    private SysOrgService sysOrgService;
    @Autowired
    private NewSysOrgService newSysOrgService;
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private TSysPostService sysPostService;
    @Autowired
    private TSysDutyalterService tSysDutyalterService;
    @Autowired
    private TSysDutyMonthService tSysDutyMonthService;
    @Autowired
    private DutyService dutyService;
    @Autowired
    private TSysDutyLogService sysDutyLogService;
    @Autowired
    private TSysTaskWorkService tSysTaskWorkService;
    @Autowired
    private SysRuleService sysRuleService;
    @Autowired
    private AsyncDuty asyncDuty;
    @Autowired
    private TLeaseBankController tLeaseBankController;
    @Autowired
    private TfwProcessInsService tfwProcessInsService;
    @Autowired
    private TSysDutyMonthService monthService;
    @Autowired
    private TSysDutyLogService tSysDutyLogService;

    @Override
    public BaseResponse dutyAddOne(TSysDuty tSysDuty) {
        BaseResponse<BizGeneralResponse> baseResponse = new BaseResponse<>();
        if (ObjectHelper.isNotEmpty(tSysDuty) && StringHelper.isNotEmpty(tSysDuty.getId())) {
            TSysDuty data = BeanHelper.beanToBean(tSysDuty, TSysDuty.class);
            boolean result = this.updateById(data);
            baseResponse.setData(
                    BizGeneralResponse.builder().result(TypeHelper.castToString(result)).build());
        }
        return baseResponse;
    }

    @Override
    public BaseResponse auditEcho(Person person) throws Exception {
        BaseResponse<Object> response = new BaseResponse<>();
        if (ObjectHelper.isEmpty(person)) {
            throw new BusinessException("请求参数有误");
        }
        String id = person.getId();
        TSysDuty tSysDuty = this.getById(id);
        String deptId = tSysDuty.getDeptId();
        QueryWrapper<SysOrg> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(SysOrg.ORG_ID, deptId);
        SysOrg sysOrg = sysOrgService.getOne(queryWrapper);
        response.setData(sysOrg);
        return response;
    }

    @Override
    public BaseResponse auditUpdate(TSysDutyalter tSysDutyalter) throws Exception {
        BaseResponse<Object> response = new BaseResponse<>();
        if (ObjectHelper.isEmpty(tSysDutyalter)) {
            throw new BusinessException("请求参数有误");
        }
        String id = tSysDutyalter.getId();
        TSysDutyalter one = tSysDutyalterService.getById(id);
        String processStatus = tSysDutyalter.getProcessStatus();
        if (("1").equals(one.getStatus())) {
            one.setProcessStatus(processStatus);
            one.setProcessId(tSysDutyalter.getProcessId());
            one.setRejectOpinion(tSysDutyalter.getRejectOpinion());
            one.setId(id);
            tSysDutyalterService.updateById(one);
            if ("5".equals(processStatus)) {
                String refId = one.getRefId();
                TSysDuty duty = new TSysDuty();
                duty.setId(refId);
                duty.setStatus("1");
                duty.setDeleteCause(one.getAdjustCause());
                duty.setRejectOpinion(one.getRejectOpinion());
                dutyService.updateById(duty);
            }
        } else {
            if ("5".equals(processStatus)) {
                //同步修改记录表数据到值班表
                TSysDuty duty = new TSysDuty();
                String nowPerson = one.getNowPerson();
                String[] split = nowPerson.split("-");
                duty.setDeptName(split[0]);
                duty.setName(split[1]);
                duty.setId(one.getId());
                duty.setStatus("0");
                duty.setProcessStatus(processStatus);
                QueryWrapper<TSysDuty> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("id", one.getRefId());
                this.update(duty, queryWrapper);
            }
        }
        return response;
    }

    @Override
    @Transactional
    public BaseResponse add(List<Duty> duty) throws Exception {
        if (ObjectHelper.isEmpty(duty)) {
            throw new BusinessException("请求参数有误");
        }
        BaseResponse<TSysDutyMonth> response = new BaseResponse<>();
        UserInfo loginUser = ContextUtils.getLoginUser();
        SysOrg sysOrg = sysOrgService.getById(loginUser.getOrgId());
        if (Objects.isNull(sysOrg)) {
            throw new BusinessException("当前登录人部门信息不存在，请联系管理员！");
        }
        Duty duty1 = duty.get(0);
        TSysDutyMonth tSysDutyMonth = BeanHelper.beanToBean(duty1, TSysDutyMonth.class);
        String tdmid = IdHelper.getId32bit();
        String dutyDate = tSysDutyMonth.getDutyDate();
        String split1 = split(dutyDate);
        // 判断是否是历史月
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMM");
        //当前年月
        String format = simpleDateFormat.format(new Date());
        //正在修改的年月
        String replace = split1.replace("-", "");
        if (replace.compareTo(format) < 0) {
            throw new BusinessException("历史月不能创建值班信息");
        }
        tSysDutyMonth.setId(tdmid);
        tSysDutyMonth.setDutyDate(split1);
        tSysDutyMonth.setCompanyId(sysOrg.getOrgId());
        tSysDutyMonth.setOrgId(sysOrg.getOrgId());
        tSysDutyMonth.setCompanyName(sysOrg.getOrgName());
        tSysDutyMonth.setCreateBy(loginUser.getUserId());
        tSysDutyMonth.setCreateDate(new Date());
        tSysDutyMonth.setStatus("0");
        tSysDutyMonth.setProcessStatus("3");
        QueryWrapper<TSysDutyMonth> query = new QueryWrapper<>();
        query.eq("duty_date", split1)
                .eq("company_id", sysOrg.getOrgId())
                .eq("unit_belong", tSysDutyMonth.getUnitBelong());
        TSysDutyMonth one = tSysDutyMonthService.getOne(query);
        List<Person> list = null;
        if (one == null) {
            tSysDutyMonthService.save(tSysDutyMonth);
            list = constructorDuty(duty, tdmid, sysOrg, loginUser);
        } else {
            throw new BusinessException("当月值班信息已创建，请勿重复创建");
//            String id = one.getId();
//            list = constructorDuty(duty, id, sysOrg, loginUser);
        }
//        TSysDutyMonth dutyMonth = new TSysDutyMonth();
//        dutyMonth.setId(tdmid);
//        dutyMonth.setDutyDate(split1);
//        dutyMonth.setCreateDate(new Date());
        //启动流程
        ProcessInsStartResult getstart = null;
        try {
            getstart = getstart(loginUser, tSysDutyMonth);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException("启动进程失败");
        }

        //启动流程结束

        //
        TSysDutyMonth dutyMonth = new TSysDutyMonth();
        dutyMonth.setId(tSysDutyMonth.getId());
        dutyMonth.setProcessId(getstart.getCode());
        BaseResponse baseResponse = monthService.dutyAddMonth(dutyMonth);
        if (baseResponse.getCode() != 200) {
            throw new BusinessException("值班人员整月添加审核状态修改接口失败");
        }
        return baseResponse;
    }

    public ProcessInsStartResult getstart(UserInfo loginUser, TSysDutyMonth tSysDutyMonth) {
        SysOrg sysOrg = sysOrgService.getById(loginUser.getOrgId());
        ProcessDefStartParam processDefStartParam = new ProcessDefStartParam("monthDuty");
        processDefStartParam.setBizKey(tSysDutyMonth.getId());
        Map<String, Object> variables = new HashMap<>();
        variables.put("processStatus", tSysDutyMonth.getProcessStatus());
        variables.put("status", tSysDutyMonth.getStatus());
        variables.put("dutyDate", tSysDutyMonth.getDutyDate());
        variables.put("treeLevel", sysOrg.getTreeLevel());
        processDefStartParam.setVariables(variables);
        if (StringHelper.isBlank(processDefStartParam.getUserId())) {
            processDefStartParam.setUserId(loginUser.getUserId());
        }

        if (StringHelper.isBlank(processDefStartParam.getOrgId())) {
            UserInfo curUser = ContextUtils.getLoginUser();
            processDefStartParam.setOrgId(curUser.getOrgId());
        }

        if (StringHelper.isBlank(processDefStartParam.getBizKey())) {
            processDefStartParam.setBizKey(IdHelper.getId32bitTime());
        }

        try {
            ProcessInsStartParams processInsStartParams = (ProcessInsStartParams) BeanHelper.beanToBean(processDefStartParam, ProcessInsStartParams.class);
            ProcessInsStartResult processInsStartResult = this.tfwProcessInsService.startProcessInsByKey(processInsStartParams);
            return processInsStartResult;
        } catch (Exception var5) {
            log.error("流程定义-启动流程实例 ERROR: " + var5);
            throw new ApiException(ProcessDefEnumCode.START_FAILED.transform());
        }
    }

    //构造保存duty数据
    private List<Person> constructorDuty(List<Duty> duty, String tdmid, SysOrg sysOrg, UserInfo loginUser) throws Exception {
        List<TSysDuty> tSysDuties = new ArrayList<>();
        List<Person> list = new ArrayList<>();
        for (Duty item : duty) {
            if (item.getPersonList() != null) {
                int i = 0;
                for (Person s : item.getPersonList()) {
                    TSysDuty tSysDuty = BeanHelper.beanToBean(s, TSysDuty.class);
                    SysOrg org = sysOrgService.getById(tSysDuty.getDeptId());
                    tSysDuty.setDeptName(org.getOrgName());
                    tSysDuty.setCompanyId(sysOrg.getOrgId());
                    tSysDuty.setCompanyName(sysOrg.getOrgName());
                    tSysDuty.setCreateBy(loginUser.getUserId());
                    tSysDuty.setCreateDate(new Date());
                    tSysDuty.setTenantName(item.getTenantName());
                    tSysDuty.setTenantId(item.getTenantId());
                    tSysDuty.setUnitBelong(item.getUnitBelong());
                    String id = IdHelper.getId32bit();
                    tSysDuty.setId(id);
                    tSysDuty.setDutyDate(item.getDutyDate());
                    tSysDuty.setRefId(tdmid);
                    tSysDuty.setStatus("0");
                    tSysDuty.setProcessStatus("3");
                    tSysDuty.setIsLeader(i == 0 ? "1":"0");
                    tSysDuty.setSort(i);
                    // 检查同一个班次是否添加相同人员
                    checkRepetition(tSysDuty);
                    tSysDuties.add(tSysDuty);
                    Person person = new Person();
                    person.setName(s.getName());
                    person.setId(id);
                    list.add(person);
                    i++;
                }
            }
        }
        tSysDuties.stream().forEach(s -> {
            this.save(s);
        });
        return list;
    }

    //返回部门名称
    private String returnDeptName(String deptID) {
        QueryWrapper<SysOrg> wrapper = new QueryWrapper<>();
        wrapper.eq(SysOrg.ORG_ID, deptID);
        SysOrg one = sysOrgService.getOne(wrapper);
        return one.getOrgName();
    }

    //返回部门下的用户电话
    private String returnPhone(String deptID) {
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(SysUser.ORG_ID, deptID);
        SysUser one = sysUserService.getOne(queryWrapper);
        return one.getPhoneNo();
    }

    private void checkRepetition(TSysDuty tSysDuty) throws Exception {
        QueryWrapper<TSysDuty> tSysDutyQueryWrapper = new QueryWrapper<>();
        tSysDutyQueryWrapper.eq("company_id", tSysDuty.getCompanyId())
                .eq("company_name", tSysDuty.getCompanyName())
                .eq("unit_belong", tSysDuty.getUnitBelong())
                .eq("classes", tSysDuty.getClasses())
                .eq("name", tSysDuty.getName())
                .ne("status", BizConstants.STATUS_DELETE)
                .eq("duty_date", tSysDuty.getDutyDate());
        TSysDuty one = this.getOne(tSysDutyQueryWrapper);
        if (one != null) {
            throw new BusinessException("同一个班次请勿重复添加相同的值班人");
        }
    }

    private void setTheMaximumSort(TSysDuty tSysDuty) {
        QueryWrapper<TSysDuty> tSysDutyQueryWrapper = new QueryWrapper<>();
        tSysDutyQueryWrapper.eq("company_id", tSysDuty.getCompanyId())
                .eq("unit_belong", tSysDuty.getUnitBelong())
                .eq("classes", tSysDuty.getClasses())
                .ne("status", BizConstants.STATUS_DELETE)
                .eq("duty_date", tSysDuty.getDutyDate());
        int count = this.count(tSysDutyQueryWrapper);
        if (count > 0) {
            tSysDuty.setSort(count);
            tSysDuty.setIsLeader("0");
        }else {
            tSysDuty.setSort(0);
            tSysDuty.setIsLeader("1");
        }
    }

    @Override
    public BaseResponse inserts(TSysDuty tSysDuty) throws Exception {
        if (ObjectHelper.isEmpty(tSysDuty)) {
            throw new BusinessException("请求参数有误");
        }
        BaseResponse<Object> response = new BaseResponse<>();
        UserInfo loginUser = ContextUtils.getLoginUser();
        SysOrg sysOrg = sysOrgService.getById(loginUser.getOrgId());
        if (Objects.isNull(sysOrg)) {
            throw new BusinessException("当前登录人部门信息不存在，请联系管理员！");
        }
        String dutydate = split(tSysDuty.getDutyDate());
        QueryWrapper<TSysDutyMonth> query = new QueryWrapper<>();
        query.eq("duty_date", dutydate)
                .eq("company_id", loginUser.getOrgId())
                .eq("unit_belong", tSysDuty.getUnitBelong());
        TSysDutyMonth one = tSysDutyMonthService.getOne(query);
        if (one == null) {
            throw new BusinessException("请先创建" + dutydate + "月值班表");
        }
        String id = IdHelper.getId32bit();
        SysOrg org = sysOrgService.getById(tSysDuty.getDeptId());
        String classes = tSysDuty.getClasses();
        tSysDuty.setDeptName(org.getOrgName());
        tSysDuty.setCompanyId(sysOrg.getOrgId());
        tSysDuty.setRefId(one.getId());
        tSysDuty.setCompanyName(sysOrg.getOrgName());
        tSysDuty.setCreateBy(loginUser.getUserId());
        tSysDuty.setCreateDate(new Date());
        tSysDuty.setDeptName(tSysDuty.getDeptName());
        tSysDuty.setId(id);
        tSysDuty.setStatus("0");
        tSysDuty.setProcessStatus("3");
        //检查同一个班次是否重复添加同一个值班人员
        checkRepetition(tSysDuty);
        setTheMaximumSort(tSysDuty);
        boolean result = this.save(tSysDuty);
        if (result) {
            response.setData(id);
            // 发消息  北京粮库新增张艳丽5月12日早班（8:00~12:00）值班。
            String dutyDate = tSysDuty.getDutyDate();
            dutyDate = dutyDate.substring(0, dutyDate.lastIndexOf("-"));
            TSysDutyMonth dutyMonth = tSysDutyMonthService.getOne(new QueryWrapper<TSysDutyMonth>()
                            .eq("company_id", org.getParentId())
                            .eq("unit_belong", tSysDuty.getUnitBelong())
                            .eq("duty_date", dutyDate)
                            .ne("status", BizConstants.STATUS_DELETE)
//                    .eq("process_status","5")
            );
            String time = "";
            if ("早班".equals(classes)) {
                time = dutyMonth.getMorTime();
            } else if ("中班".equals(classes)) {
                time = dutyMonth.getNoonTime();
            } else if ("晚班".equals(classes)) {
                time = dutyMonth.getLateTime();
            } else if ("全天".equals(classes)) {
                time = dutyMonth.getAllTime();
            }
            String msgModel = sysOrg.getOrgName() + "(" + tSysDuty.getUnitBelong() + ")新增" + tSysDuty.getName() + tSysDuty.getDutyDate() + "日" + tSysDuty.getClasses() + "(" + time + ") 值班";
            sendMessage(loginUser.getOrgId(), id, msgModel);
        } else {
            throw new BusinessException("新增失败");
        }
        return response;
    }

    @Override
    public BaseResponse update(TSysDuty tSysDuty) throws Exception {
        BaseResponse<Object> response = new BaseResponse<>();
        if (ObjectHelper.isEmpty(tSysDuty)) {
            throw new BusinessException("请求参数有误");
        }
        UserInfo loginUser = ContextUtils.getLoginUser();
        SysOrg sysOrg = sysOrgService.getById(loginUser.getOrgId());
        if (Objects.isNull(sysOrg)) {
            throw new BusinessException("当前登录人部门信息不存在，请联系管理员！");
        }
        String id = tSysDuty.getId();
        TSysDuty duty = this.getById(id);
        if (ObjectHelper.isEmpty(duty) || !("0".equals(duty.getStatus()))) {
            throw new BusinessException("数据不存在");
        }
        TSysDutyalter tSysDutyalter = BeanHelper.beanToBean(duty, TSysDutyalter.class);
        //原值班人员
        String origPerson = duty.getDeptName() + "-" + duty.getName();
        //现值班人员
        String nowPerson = tSysDuty.getDeptName() + "-" + tSysDuty.getName();
        if (origPerson.equals(nowPerson)) {
            throw new BusinessException("该值班人已存在，请重新选择");
        }
        tSysDutyalter.setOrigPerson(origPerson);
        tSysDutyalter.setNowPerson(nowPerson);
        //操作时间
        tSysDutyalter.setCreateDate(new Date());
        //操作人
        tSysDutyalter.setOperator(loginUser.getUserName());
        //操作人id
        tSysDutyalter.setCreateBy(loginUser.getUserId());
        String recordId = IdHelper.getId32bit();
        tSysDutyalter.setId(recordId);
        tSysDutyalter.setRefId(id);
        tSysDutyalter.setCompanyId(sysOrg.getOrgId());
        tSysDutyalter.setProcessStatus("3");
        tSysDutyalter.setStatus("0");
        QueryWrapper<TSysDutyalter> wrapper = new QueryWrapper<>();
        wrapper.eq("ref_id", id);
        TSysDutyalter one = tSysDutyalterService.getOne(wrapper);
        if (one == null) {
            tSysDutyalterService.save(tSysDutyalter);
        }
        if (one != null && ("3".equals(one.getProcessStatus()))) {
            throw new BusinessException("数据审核中，请勿重复提交");
        }
        TSysDutyalter tSysDutyalter1 = new TSysDutyalter();
        tSysDutyalter1.setId(recordId);
        response.setData(tSysDutyalter1);
        return response;
    }

    @Override
    public BaseResponse updateByDuty(TSysDuty tSysDuty) throws Exception {
        BaseResponse<Object> response = new BaseResponse<>();
        if (ObjectHelper.isEmpty(tSysDuty)) {
            throw new BusinessException("请求参数有误");
        }
        UserInfo loginUser = ContextUtils.getLoginUser();
        SysOrg sysOrg = sysOrgService.getById(loginUser.getOrgId());
        if (Objects.isNull(sysOrg)) {
            throw new BusinessException("当前登录人部门信息不存在，请联系管理员！");
        }
        String id = tSysDuty.getId();
        TSysDuty duty = this.getById(id);
        duty.setId(id);
        if (ObjectHelper.isEmpty(duty) || !("0".equals(duty.getStatus()))) {
            throw new BusinessException("数据不存在");
        }
        TSysDutyalter tSysDutyalter = BeanHelper.beanToBean(duty, TSysDutyalter.class);
        //原值班人员
        String origPerson = duty.getDeptName() + "-" + duty.getName();
        //现值班人员
        SysOrg service = sysOrgService.getById(tSysDuty.getDeptId());
        String nowPerson = service.getOrgName() + "-" + tSysDuty.getName();
        if (origPerson.equals(nowPerson)) {
            throw new BusinessException("该值班人已存在，请重新选择");
        }
        String dutyDate = duty.getDutyDate();
        dutyDate = dutyDate.substring(0, dutyDate.lastIndexOf("-"));
        TSysDutyMonth dutyMonth = tSysDutyMonthService.getOne(new QueryWrapper<TSysDutyMonth>()
                        .eq("company_id", sysOrg.getOrgId())
                        .eq("unit_belong", tSysDuty.getUnitBelong())
                        .eq("duty_date", dutyDate)
                        .ne("status", BizConstants.STATUS_DELETE)
//                .eq("process_status","5")
        );
        tSysDutyalter.setDutyPattern(dutyMonth.getDutyPattern());
        tSysDutyalter.setOrigPerson(origPerson);
        tSysDutyalter.setNowPerson(nowPerson);
        //操作时间
        tSysDutyalter.setCreateDate(new Date());
        //操作人
        tSysDutyalter.setOperator(loginUser.getUserName());
        //操作人id
        tSysDutyalter.setCreateBy(loginUser.getUserId());
        String recordId = IdHelper.getId32bit();
        tSysDutyalter.setId(recordId);
        tSysDutyalter.setRefId(id);
        tSysDutyalter.setCompanyId(sysOrg.getOrgId());
        tSysDutyalter.setProcessStatus("3");
        tSysDutyalter.setStatus("0");
        tSysDutyalterService.save(tSysDutyalter);
        duty.setName(tSysDuty.getName());
        duty.setPhone(tSysDuty.getPhone());
        duty.setUserId(tSysDuty.getUserId());
        duty.setDeptId(tSysDuty.getDeptId());
        duty.setDeptName(service.getOrgName());
        duty.setAdjustCause(tSysDuty.getAdjustCause());
        boolean result = this.updateById(duty);
        if (result) {
            String time = "";
            if ("早班".equals(duty.getClasses())) {
                time = dutyMonth.getMorTime();
            } else if ("中班".equals(duty.getClasses())) {
                time = dutyMonth.getNoonTime();
            } else if ("晚班".equals(duty.getClasses())) {
                time = dutyMonth.getLateTime();
            } else if ("全天".equals(duty.getClasses())) {
                time = dutyMonth.getAllTime();
            }
            // 消息通知  北京粮库5月12日早班（8:00~12:00）值班人员张华调整为李明。
            String msgTemplate = sysOrg.getOrgName() + "(" + dutyMonth.getUnitBelong() + ")" + duty.getDutyDate() + "日" + duty.getClasses() + "(" + time + ")值班人员" + duty.getName() + "调整为" + tSysDuty.getName();
            sendMessage(loginUser.getOrgId(), id, msgTemplate);
        }
        response.setData(duty);
        return response;
    }

    @Override
    public BaseResponse delete(TSysDuty tSysDuty) throws Exception {
        UserInfo loginUser = ContextUtils.getLoginUser();
        SysOrg sysOrg = sysOrgService.getById(loginUser.getOrgId());
        if (Objects.isNull(sysOrg)) {
            throw new BusinessException("当前登录人部门信息不存在，请联系管理员！");
        }
        BaseResponse<Object> response = new BaseResponse<>();
        if (ObjectHelper.isEmpty(tSysDuty)) {
            throw new BusinessException("请求参数有误");
        }
        String refId = tSysDuty.getId();
        TSysDuty duty = this.getById(refId);
        duty.setStatus(BizConstants.STATUS_DELETE);
        duty.setDeleteCause(tSysDuty.getDeleteCause());
        //如果删除的是领导人
        if (duty.getIsLeader() != null && duty.getIsLeader().equals("1")){
            QueryWrapper<TSysDuty> tSysDutyQueryWrapper = new QueryWrapper<>();
            tSysDutyQueryWrapper.eq("company_id", tSysDuty.getCompanyId())
                    .eq("company_name", tSysDuty.getCompanyName())
                    .eq("unit_belong", tSysDuty.getUnitBelong())
                    .eq("classes", tSysDuty.getClasses())
                    .ne("status", BizConstants.STATUS_DELETE)
                    .eq("duty_date", tSysDuty.getDutyDate())
                    .orderByAsc("sort")
                    .last("limit 1");
            TSysDuty one = this.getOne(tSysDutyQueryWrapper);
            //设置排序最小的人为新的领导
            if (one != null){
                one.setIsLeader("1");
                this.updateById(one);
            }
        }
        boolean result = this.updateById(duty);
        if (result) {
            String dutyTime = "";
            TSysDutyMonth one = tSysDutyMonthService.getOne(new QueryWrapper<TSysDutyMonth>().eq("id", duty.getRefId()).ne("status", BizConstants.STATUS_DELETE));
            if ("早班".equals(duty.getClasses())) {
                dutyTime = one.getMorTime();
            } else if ("中班".equals(duty.getClasses())) {
                dutyTime = one.getNoonTime();
            } else if ("晚班".equals(duty.getClasses())) {
                dutyTime = one.getLateTime();
            } else if ("全天".equals(duty.getClasses())) {
                dutyTime = one.getAllTime();
            }
            String dutyDetail = duty.getCompanyName() + "(" + one.getUnitBelong() + ")" + duty.getName() + duty.getDutyDate() +
                    duty.getClasses() + "值班(" + dutyTime + ")" + "已取消";
            sendMessage(loginUser.getOrgId(), tSysDuty.getId(), dutyDetail);
        }
//        if (ObjectHelper.isEmpty(duty) || !("0".equals(duty.getStatus()))) {
//            throw new BusinessException("数据不存在");
//        }
//        TSysDutyalter tSysDutyalter = BeanHelper.beanToBean(duty, TSysDutyalter.class);
//        tSysDutyalter.setAdjustCause(tSysDuty.getDeleteCause());
//        tSysDutyalter.setRefId(refId);
//        String id = IdHelper.getId32bit();
//        tSysDutyalter.setId(id);
//        tSysDutyalter.setStatus("1");
//        tSysDutyalter.setProcessStatus("3");
//        QueryWrapper<TSysDutyalter> wrapper = new QueryWrapper<>();
//        wrapper.eq("ref_id", id);
//        TSysDutyalter one = tSysDutyalterService.getOne(wrapper);
//        if (one == null) {
//            tSysDutyalterService.save(tSysDutyalter);
//        }
//        if (one != null && ("3".equals(one.getProcessStatus()))) {
//            throw new BusinessException("数据审核中，请勿重复提交");
//        }
//        TSysDutyalter tSysDutyalter1 = new TSysDutyalter();
        response.setData(tSysDuty);
        return response;
    }

    @Autowired
    private TMsgNoticeService tMsgNoticeService;

    /**
     * @param orgId      机构id
     * @param bizKeyId   业务id
     * @param dutyDetail 消息模板
     */
    public void sendMessage(String orgId, String bizKeyId, String dutyDetail) {
        MsgTemplateVO msgTemplateVO = new MsgTemplateVO();
        msgTemplateVO.setTemplateContent(dutyDetail);
        msgTemplateVO.setTemplateType("notice");
        msgTemplateVO.setTemplateTypeName("通知");
        List<SysUser> list = sysUserService.list(new QueryWrapper<SysUser>().eq(SysUser.ORG_ID, orgId).ne(SysUser.STATUS, BizConstants.STATUS_DELETE));
        List<String> userIdList = list.stream().map(SysUser::getUserId).collect(Collectors.toList());
        // 字典编码
        String bizKey = "dutysendmsg";
        List<TMsgNotice> tMsgNotices = tMsgNoticeService.generateMsgNotice(bizKey, bizKeyId, userIdList, msgTemplateVO);
        tMsgNoticeService.saveBatch(tMsgNotices);
    }

    @Override
//    public BaseResponse<List<PersonDuty>> getLists(TSysDutyMonth tSysDuty) throws Exception {
    public BaseResponse<List<Duty>> getLists(TSysDutyMonth tSysDuty) throws Exception {
        QueryWrapper<TSysDutyMonth> wrapper = new QueryWrapper<>();
        UserInfo loginUser = ContextUtils.getLoginUser();
        String orgId = tSysDuty.getOrgId();
        if (StringUtils.isNotBlank(orgId)) {
            loginUser.setOrgId(orgId);
        }
        SysOrg sysOrg = sysOrgService.getById(loginUser.getOrgId());
        if (ObjectHelper.isNotEmpty(tSysDuty.getUnitBelong())) {
            wrapper.eq("unit_belong", tSysDuty.getUnitBelong());
        } else {
            wrapper.eq("unit_belong", "本单位");
        }

        if (ObjectHelper.isNotEmpty(tSysDuty.getTenantId())) {
            wrapper.eq("tenant_id", tSysDuty.getTenantId());
        }
        BaseResponse<List<Duty>> response = new BaseResponse<>();
        //此处用这个字段判断并没有什么含义只是为了导出时方便区分条件使用
        if (tSysDuty.getType() != null) {
            List<String> allMonths = new ArrayList<>();
            //如果不为空，获取所有月份
            if (StringUtils.isNotBlank(tSysDuty.getEndDate()) && StringUtils.isNotBlank(tSysDuty.getStartDate())) {
                String startDateString = tSysDuty.getStartDate();
                String endDateString = tSysDuty.getEndDate();
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-M-d");
                LocalDate startDate = LocalDate.parse(startDateString, formatter);
                LocalDate endDate = LocalDate.parse(endDateString, formatter);
                allMonths = getAllMonths(startDate, endDate);
            }
            //拿到所有月份的数据
            List<Duty> dutiesList = new ArrayList<>();
            String[] split = new String[10];
            if (ObjectHelper.isNotEmpty(tSysDuty.getCompanyId())) {
                split = tSysDuty.getCompanyId().split(",");
            }
            //如果机构id的长度大于0
            if (split.length > 0) {
                for (String companyId : split) {
                    QueryWrapper<TSysDutyMonth> queryWrapper = wrapper.clone();
                    if (ObjectHelper.isNotEmpty(tSysDuty.getCompanyId())) {
                        queryWrapper.eq("company_id", companyId);
                    } else {
                        queryWrapper.eq("company_id", sysOrg.getOrgId());
                    }
                    for (String allMonth : allMonths) {
                        QueryWrapper<TSysDutyMonth> queryWrapper1 = queryWrapper.clone();
                        if (ObjectHelper.isNotEmpty(allMonth)) {
                            queryWrapper1 = queryWrapper1.like("duty_date", allMonth);
                        }
                        TSysDutyMonth one = tSysDutyMonthService.getOne(queryWrapper1);
                        if (one != null) {
                            if ("5".equals(one.getProcessStatus())) {
                                QueryWrapper<TSysDuty> tSysDutyQueryWrapper = new QueryWrapper<>();
                                tSysDutyQueryWrapper.in("ref_id", one.getId());
                                tSysDutyQueryWrapper.eq("status", "0");
                                if (StringUtils.isNotBlank(tSysDuty.getStartDate())) {
                                    tSysDutyQueryWrapper.ge("duty_date", tSysDuty.getStartDate());
                                }
                                if (StringUtils.isNotBlank(tSysDuty.getEndDate())) {
                                    tSysDutyQueryWrapper.le("duty_date", tSysDuty.getEndDate());
                                }
                                tSysDutyQueryWrapper.orderByAsc("duty_date");
                                tSysDutyQueryWrapper.orderByAsc("sort");
                                List<TSysDuty> list = this.list(tSysDutyQueryWrapper);
                                //确定领导
                                asyncDuty.returnDutyList(list, one);
                                //===
                                //按天返回整月数据，不对班次进行分组
                                List<Duty> duties = returnPersonDay(list, one);
                                dutiesList.addAll(duties);
                            }
                        }
                    }
                }
            }
            response.setData(dutiesList);
        } else {
            if (Objects.isNull(sysOrg)) {
                throw new BusinessException("当前登录人部门信息不存在，请联系管理员！");
            }
            if (ObjectHelper.isNotEmpty(tSysDuty.getCompanyId())) {
                wrapper.in("company_id", tSysDuty.getCompanyId());
            } else {
                wrapper.eq("company_id", sysOrg.getOrgId());
            }
            // TODO 默认展示哪个租赁公司
            if (ObjectHelper.isNotEmpty(tSysDuty.getDutyDate())) {
                wrapper.like("duty_date", tSysDuty.getDutyDate());
            } else {
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM");
                String format = simpleDateFormat.format(new Date());
                wrapper.like("duty_date", format);
            }
            String rule = sysRuleService.dataRuleScope(DefaultRule.DEPT_ALL.name());
            if (StringUtils.isNotEmpty(rule)) {
                wrapper.apply(rule);
            }
            wrapper.eq("status", "0");
            TSysDutyMonth one = tSysDutyMonthService.getOne(wrapper);
            if (one == null) {
                throw new BusinessException("该月没有数据");
            }
            if ("5".equals(one.getProcessStatus())) {
                QueryWrapper<TSysDuty> tSysDutyQueryWrapper = new QueryWrapper<>();
                tSysDutyQueryWrapper.in("ref_id", one.getId());
                tSysDutyQueryWrapper.eq("status", "0");
                tSysDutyQueryWrapper.orderByAsc("sort");
                List<TSysDuty> list = this.list(tSysDutyQueryWrapper);
                //确定领导
                asyncDuty.returnDutyList(list, one);
                //===
                //按天返回整月数据，不对班次进行分组
                List<Duty> duties = returnPersonDay(list, one);
                response.setData(duties);
            }
        }
        return response;
    }
    //====
    //按天返回整月数据，对班次进行分组
//        BaseResponse<List<PersonDuty>> duty = returnDutyList(list, one);
//        return duty;


    private static List<String> getAllMonths(LocalDate startDate, LocalDate endDate) {
        List<String> monthsList = new ArrayList<>();
        YearMonth currentMonth = YearMonth.from(startDate);

        while (!currentMonth.isAfter(YearMonth.from(endDate))) {
            monthsList.add(currentMonth.format(DateTimeFormatter.ofPattern("yyyy-MM")));
            currentMonth = currentMonth.plusMonths(1);
        }

        return monthsList;
    }

    //按天返回整月数据，不对班次进行分组
    private List<Duty> returnPersonDay(List<TSysDuty> list, TSysDutyMonth one) {
        List<Duty> duties = new ArrayList<>();
        if (list.size() == 0) {
            Duty duty = BeanHelper.beanToBean(one, Duty.class);
            duties.add(duty);
            return duties;
        }
        //按照日期（dd）分组
        Map<String, List<TSysDuty>> collect = list.stream().collect(Collectors.groupingBy(item -> splitDate(item.getDutyDate())));
        for (String s : collect.keySet()) {
            //拿到分组后的每一天的数据
            List<TSysDuty> tSysDuties = collect.get(s);
            //存储每一天的多个人
            Duty duty = null;
            List<Person> people = new ArrayList<>();
            for (TSysDuty tSysDuty : tSysDuties) {
                duty = BeanHelper.beanToBean(one, Duty.class);
                duty.setDutyDate(tSysDuty.getDutyDate());
                duty.setIsCreateLog(tSysDuty.getIsCreateLog());
                String dutyLogId = tSysDuty.getDutyLogId();
                Person person = BeanHelper.beanToBean(tSysDuty, Person.class);
                person.setDutyLogDraft("0");
                person.setDutyLogId(dutyLogId);
                if (dutyLogId != null) {
                    TSysDutyLog byId = tSysDutyLogService.getById(dutyLogId);
                    if (byId != null) {
                        String status = byId.getStatus();
                        if (status.equals("3")) {
                            person.setDutyLogDraft("1");
                        }
                    }
                }
                if (StringUtils.isBlank(person.getIsCreateLog())){
                    person.setIsCreateLog("0");
                }
                //存储同一天多个人到list
                people.add(person);
                List<Person> collect1 = people.stream().sorted(Comparator.comparing(Person::getCreateDate).thenComparing(Person::getId)).collect(Collectors.toList());
                duty.setPersonList(collect1);
            }
            duties.add(duty);
        }
        return duties;
    }

    //按天返回整月数据，对班次进行分组
    public BaseResponse<List<PersonDuty>> returnDutyList(List<TSysDuty> list, TSysDutyMonth one) {
        try {
            TimeUnit.SECONDS.sleep(60);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //按照日期（dd）分组
        Map<String, List<TSysDuty>> collect = list.stream().collect(Collectors.groupingBy(item -> splitDate(item.getDutyDate())));
        List<PersonDuty> duties = new ArrayList<>();

        for (String s : collect.keySet()) {
            //拿到分组后的每一天数据
            List<TSysDuty> tSysDuties = collect.get(s);
            //存储每一天的多个人
            List<Person> people = new ArrayList<>();
            PersonDuty duty = null;
            for (TSysDuty tSysDuty : tSysDuties) {
                duty = BeanHelper.beanToBean(tSysDuty, PersonDuty.class);
                Person person = new Person();
                person.setId(tSysDuty.getId());
                person.setClasses(tSysDuty.getClasses());
                person.setPhone(tSysDuty.getPhone());
                person.setAdjustCause(tSysDuty.getAdjustCause());
                person.setDeptName(tSysDuty.getDeptName());
                person.setName(tSysDuty.getName());
                person.setCreateDate(tSysDuty.getCreateDate());
                person.setIsLeader(tSysDuty.getIsLeader());
                //存储同一天多个人到list
                people.add(person);
                duty.setPersonList(people);
            }
            //按值班模式分组
            Map<String, List<Person>> map = people.stream().collect(Collectors.groupingBy(p -> p.getClasses()));
            //==============
            // 排序后的数据
            Map<String, List<Person>> reMap = new HashMap<>();
            map.keySet().stream().forEach(item -> {
                List<Person> people1 = map.get(item);
                //对分组后的数据按createDate升序排序
                List<Person> collect1 = people1.stream().sorted(Comparator.comparing(p -> p.getCreateDate())).collect(Collectors.toList());
                saveLeader(collect1);
                reMap.put(item, collect1);
            });
            //=========================
            duty.setPersonList(null);
            duty.setMapList(reMap);
            duty.setMorTime(one.getMorTime());
            duty.setLateTime(one.getLateTime());
            duty.setAllTime(one.getAllTime());
            duty.setNoonTime(one.getNoonTime());
            duty.setDutyPattern(one.getDutyPattern());
            duty.setId(one.getId());
            //将同一天数据存到list
            duties.add(duty);
        }
        BaseResponse<List<PersonDuty>> response = new BaseResponse<>();
        response.setData(duties);
        return response;
    }

    private void saveLeader(List<Person> collect1) {
        Map<String, Person> isLeader = collect1.stream().collect(Collectors.groupingBy(Person::getClasses, Collectors.collectingAndThen(
                Collectors.reducing((c1, c2) -> c1), Optional::get)));
        //将获取到的每个班次的第一个人保存为领导
        isLeader.keySet().stream().forEach(key -> {
            Person person = isLeader.get(key);
            TSysDuty duty = new TSysDuty();
            duty.setId(person.getId());
            duty.setIsLeader("1");
            this.updateById(duty);
        });
    }

    private String splitDate(String dutyDate) {
        String[] split = dutyDate.split("-");
        String s = split[split.length - 1];
        return s;
    }

    private String split(String dutyDate) {
        String[] split = dutyDate.split("-");
        dutyDate = split[0] + "-" + split[1];
        return dutyDate;
    }

    // map收集器用于map值是list时list排序
    public <T> Collector<T, ?, List<T>> toSortedList(Comparator<? super T> c) {
        return Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(c)), ArrayList::new);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResponse<List<Person>> imports(MultipartFile file, TSysDuty tSysDuty) throws Exception {
        UserInfo loginUser = ContextUtils.getLoginUser();
        SysOrg sysOrg = sysOrgService.getById(loginUser.getOrgId());
        if (Objects.isNull(sysOrg)) {
            throw new BusinessException("当前登录人部门信息不存在，请联系管理员！");
        }
        Workbook workbook = null;
        InputStream inputStream = null;
        BaseResponse<List<Person>> response = new BaseResponse<>();
        List<Person> people = new ArrayList<>();
        try {
            inputStream = file.getInputStream();
            // 读取Excel⽂件⼯作表
            workbook = PoiExcelUtils.readFile(inputStream, file.getOriginalFilename());
            //取得第⼀个⼯作表
            Sheet sheet = workbook.getSheetAt(0);
            //报表上传的每条数据
            List<Map<Integer, Object>> list = PoiExcelUtils.getBody(sheet, 13, 5);
            //检查数据安全
            checkReportData(list);
            //获取年月对应表id
            TSysDuty dutyMonthId = getDutyMonthId(list, tSysDuty, sysOrg, loginUser);
            String monthId = dutyMonthId.getId();
            list.stream().forEach(item -> {
                Person person = this.saveDuty(item, tSysDuty, sysOrg, loginUser, monthId);
                people.add(person);
            });
            response.setData(people);
            // 导入成功启动流程
            startProcess(monthId, dutyMonthId.getDutyDate());
            return response;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != workbook) {
                    workbook.close();
                }
                if (null != inputStream) {
                    inputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return response;
    }

    @Autowired
    private ProcessDefinitionController processDefinitionController;

    /**
     * 启动流程
     *
     * @param monthId
     */
    private void startProcess(String monthId, String dutyDate) {
        ProcessDefStartParam processDefStartParam = new ProcessDefStartParam("monthDuty");
        processDefStartParam.setBizKey(monthId);
        processDefStartParam.setProcessDefinitionKey("monthDuty");
        Map<String, Object> map = new HashMap<>();
        map.put("processStatus", 3);
        map.put("status", 0);
        map.put("dutyDate", dutyDate);
        processDefStartParam.setVariables(map);
        // 获取流程实例id
        String result = processDefinitionController.startProcessIns(processDefStartParam).getData().getResult();
        // 保存流程状态
        TSysDutyMonth tSysDutyMonth = new TSysDutyMonth();
        tSysDutyMonth.setId(monthId);
        tSysDutyMonth.setProcessId(result);
        try {
            tSysDutyMonthService.dutyAddMonth(tSysDutyMonth);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 判断对象中的所有属性是否为空
     *
     * @param object
     * @return
     */
    public static boolean checkObjAllFieldsIsNull(Object object) {
        if (null == object) {
            return true;
        }
        try {
            for (Field f : object.getClass().getDeclaredFields()) {
                f.setAccessible(true);

                if (f.get(object) != null && !StringUtils.isEmpty(f.get(object).toString())) {
                    return false;
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }

    //检查字符串是不是纯数字
    public static boolean isNumberStr(String str) {
        if (str != null && !"".equals(str.trim())) {
            return str.matches("^[0-9]*$");
        } else {
            return false;
        }
    }

    private void checkReportData(List<Map<Integer, Object>> list) throws Exception {
        ArrayList<TSysDutyMonth> listmonth = new ArrayList<>();
        for (Map<Integer, Object> item : list) {
            String year = item.get(2).toString();
            String month = item.get(3).toString();
            String day = item.get(4).toString();

            if (!isNumberStr(year) || !isNumberStr(month) || !isNumberStr(day)) {
                throw new BusinessException("请传正确的日期");
            }
            int intMonth = Integer.parseInt(month);
            int intDay = Integer.parseInt(day);
            if (intMonth > 12 || intMonth < 1) {
                throw new BusinessException("请传正确的日期");
            }
            if (intDay > 31 || intDay < 1) {
                throw new BusinessException("请传正确的日期");
            }
            //值班模式
            String dutyPattern = item.get(5).toString();
            if (!"早中晚班".contains(dutyPattern) && !"早晚班".contains(dutyPattern) && !"全天班".contains(dutyPattern)) {
                throw new BusinessException("请检查值班模式填写是否正确");
            }
            //值班班次
            String classes = item.get(6).toString();
            String date = null;
            if (!"".equals(year) && !"".equals(month)) {
                date = year + "/" + month;
            }
            TSysDutyMonth tSysDutyMonth = new TSysDutyMonth();
            tSysDutyMonth.setDutyDate(date);
            tSysDutyMonth.setDutyPattern(dutyPattern);
            tSysDutyMonth.setRemarks(classes);
            listmonth.add(tSysDutyMonth);
        }
        if (listmonth.size() == 0) {
            throw new BusinessException("请勿上传空模板");
        }
        for (TSysDutyMonth tSysDutyMonth : listmonth) {
            if (checkObjAllFieldsIsNull(tSysDutyMonth)) {
                throw new BusinessException("请填写完整信息后上传");
            }
            String dutyPattern = tSysDutyMonth.getDutyPattern();
            String classes = tSysDutyMonth.getRemarks();
            if ("早晚班".contains(dutyPattern)) {
                if (!classes.contains("早") && !classes.contains("晚")) {
                    throw new BusinessException("请检查值班模式和班次是否匹配");
                }
            }
            if ("早中晚班".contains(dutyPattern)) {
                if (!classes.contains("早") &&
                        !classes.contains("中") &&
                        !classes.contains("晚")) {
                    throw new BusinessException("请检查值班模式和班次是否匹配");
                }
            }
            if ("全天".contains(dutyPattern)) {
                if (!classes.contains("全天")) {
                    throw new BusinessException("请检查值班模式和班次是否匹配");
                }
            }
        }
        Map<String, List<TSysDutyMonth>> collect = listmonth.stream().collect(Collectors.groupingBy(item -> splitDate(item.getDutyDate())));
        if (collect.keySet().size() > 1) {
            throw new BusinessException("只能添加相同月份的数据");
        }
    }

    private TSysDuty getDutyMonthId(List<Map<Integer, Object>> list, TSysDuty tSysDuty, SysOrg sysOrg, UserInfo loginUser) throws Exception {
        List<DutyMonthExcel> excelList = new ArrayList<>();

        list.stream().forEach(item -> {
            DutyMonthExcel dutyMonthExcel = new DutyMonthExcel();
            String month = item.get(2) + "-" + item.get(3);
            //年月
            dutyMonthExcel.setDutyDate(month);
            //值班班次
            dutyMonthExcel.setDutyPattern(item.get(6).toString());
            //处理值班时间
            DutyDate dutyDate = new DutyDate();
            String startDate = item.get(7).toString();
            String endDate = item.get(9).toString();
            SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
            SimpleDateFormat outputFormat = new SimpleDateFormat("HH:mm");
            try {
                Date startDateObj = inputFormat.parse(startDate);
                Date endDateObj = inputFormat.parse(endDate);
                String startTime = outputFormat.format(startDateObj);
                String endTime = outputFormat.format(endDateObj);
                dutyDate.setStartTime(startTime);
                dutyDate.setEndTime(endTime);
            } catch (ParseException e) {
                dutyDate.setStartTime(startDate);
                dutyDate.setEndTime(endDate);
            }
            if (item.get(8).toString().equals("次日")) {
                dutyDate.setIsNextDay("2");
            } else {
                dutyDate.setIsNextDay("1");
            }
            dutyMonthExcel.setDutyTime(JSONObject.toJSON(dutyDate).toString());
            //值班模式
            String model = item.get(5).toString();
            dutyMonthExcel.setModel(model);
            excelList.add(dutyMonthExcel);
        });
        //按照excel中值班模式分组
        Map<String, List<DutyMonthExcel>> collect = excelList.stream().collect(Collectors.groupingBy(item -> splitDate(item.getDutyPattern())));
        //拿到分组后的值班模式集合
        Set<String> patternList = collect.keySet();
        //构造的模式时间年月对象集合
        List<DutyMonthExcel> dutyMonthExcel = new ArrayList<>();
        patternList.forEach(item -> {
            //每一个值班模式item
            List<DutyMonthExcel> dutyMonthExcels = collect.get(item);
            //每个值班模式对应的值班时间
            String dutyTime = dutyMonthExcels.get(0).getDutyTime();
            //值班年月
            String dutyDate = dutyMonthExcels.get(0).getDutyDate();
            //获取值班模式model
            String model = dutyMonthExcels.get(0).getModel();
            //构造模式时间年月对象
            DutyMonthExcel tSysDutyMonth = constructorMonth(item, dutyTime, dutyDate, model);
            dutyMonthExcel.add(tSysDutyMonth);
        });
        //存储月对象
        String monthExcelId = storeMonthExcel(dutyMonthExcel, tSysDuty, sysOrg, loginUser);
        TSysDuty tSysDuty1 = new TSysDuty();
        tSysDuty1.setId(monthExcelId);
        tSysDuty1.setDutyDate(dutyMonthExcel.get(0).getDutyDate());
        return tSysDuty1;
    }

    private String storeMonthExcel(List<DutyMonthExcel> dutyMonthExcel, TSysDuty tSysDuty, SysOrg sysOrg, UserInfo loginUser) throws Exception {
//        System.out.println(dutyMonthExcel);
        TSysDutyMonth tSysDutyMonth = BeanHelper.beanToBean(tSysDuty, TSysDutyMonth.class);
        dutyMonthExcel.stream().forEach(item -> {
            String dutyPattern = item.getDutyPattern();
            if (dutyPattern.contains("早")) {
                tSysDutyMonth.setMorTime(item.getDutyTime());
            }
            if (dutyPattern.contains("中")) {
                tSysDutyMonth.setNoonTime(item.getDutyTime());
            }
            if (dutyPattern.contains("晚")) {
                tSysDutyMonth.setLateTime(item.getDutyTime());
            }
            if (dutyPattern.contains("全")) {
                tSysDutyMonth.setAllTime(item.getDutyTime());
            }
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
            Date date = null;
            try {
                date = sdf.parse(item.getDutyDate());
            } catch (ParseException e) {
                e.printStackTrace();
            }
            String format = sdf.format(date);
            tSysDutyMonth.setDutyDate(format);
            tSysDutyMonth.setDutyPattern(item.getModel());
        });
        QueryWrapper<TSysDutyMonth> wrapper = new QueryWrapper<>();
        wrapper.eq("duty_date", tSysDutyMonth.getDutyDate())
                .eq("company_id", sysOrg.getOrgId())
                .eq("unit_belong", tSysDutyMonth.getUnitBelong())
                .eq("status", "0");
        TSysDutyMonth one = tSysDutyMonthService.getOne(wrapper);
        if (one == null) {
            String monthExcelId = IdHelper.getId32bit();
            tSysDutyMonth.setId(monthExcelId);
            tSysDutyMonth.setCompanyId(sysOrg.getOrgId());
            tSysDutyMonth.setOrgId(sysOrg.getOrgId());
            tSysDutyMonth.setCompanyName(sysOrg.getOrgName());
            tSysDutyMonth.setCreateDate(new Date());
            tSysDutyMonth.setCreateBy(loginUser.getUserId());
            tSysDutyMonth.setStatus("0");
            tSysDutyMonth.setProcessStatus("3");
            tSysDutyMonthService.save(tSysDutyMonth);
            return monthExcelId;
        } else {
            throw new BusinessException("当月值班信息已创建，请勿重复创建");
        }
//        return one.getId();
    }

    private DutyMonthExcel constructorMonth(String item, String dutyTime, String dutyDate, String model) {
        DutyMonthExcel dutyMonthExcel = new DutyMonthExcel();
        dutyMonthExcel.setDutyPattern(item);
        dutyMonthExcel.setDutyTime(dutyTime);
        dutyMonthExcel.setDutyDate(dutyDate);
        dutyMonthExcel.setModel(model);
        return dutyMonthExcel;
    }

    @SneakyThrows
    public Person saveDuty(Map<Integer, Object> item, TSysDuty duty, SysOrg sysOrg, UserInfo loginUser, String monthId) {
        TSysDuty tSysDuty = BeanHelper.beanToBean(duty, TSysDuty.class);
        String dateStr = item.get(2) + "-" + item.get(3) + "-" + item.get(4);
        tSysDuty.setDutyDate(dateStr);
        tSysDuty.setClasses(item.get(6).toString());
        String id = IdHelper.getId32bit();
        tSysDuty.setId(id);
        tSysDuty.setDeptName(item.get(10).toString());
        String name = item.get(11).toString();
        tSysDuty.setName(name);
        tSysDuty.setRefId(monthId);
        String loginName = item.get(12).toString();
        SysUser user = sysUserService.getOne(new QueryWrapper<SysUser>().eq(SysUser.ORG_ID, sysOrg.getOrgId()).eq(SysUser.LOGIN_NAME, loginName).eq(SysUser.STATUS, BizConstants.STATUS_ENABLE));
        if (user == null) {
            throw new BusinessException("请检查账号:[" + loginName + "]是否存在");
        }
        tSysDuty.setUserId(user.getUserId());
        tSysDuty.setPhone(user.getPhoneNo());
        tSysDuty.setDeptId(user.getDeptId());
//        tSysDuty.setPhone(item.get(8).toString());
        tSysDuty.setCreateBy(loginUser.getUserId());
        tSysDuty.setCreateDate(new Date());
        tSysDuty.setCompanyId(loginUser.getOrgId());
        tSysDuty.setCompanyName(sysOrg.getOrgName());
        tSysDuty.setUnitBelong(duty.getUnitBelong());
        tSysDuty.setTenantId(duty.getTenantId());
        tSysDuty.setStatus("0");
        tSysDuty.setProcessStatus("3");
        QueryWrapper<TSysDuty> queryWrapper = new QueryWrapper<>();
        if (ObjectHelper.isNotEmpty(tSysDuty.getTenantId())) {
            queryWrapper.eq("tenant_id", tSysDuty.getTenantId());
        }
        if (ObjectHelper.isNotEmpty(tSysDuty.getTenantName())) {
            queryWrapper.eq("tenant_name", tSysDuty.getTenantName());
        }
        queryWrapper.eq("company_id", tSysDuty.getCompanyId())
                .eq("duty_date", tSysDuty.getDutyDate())
                .eq("unit_belong", tSysDuty.getUnitBelong())
                .eq("classes", tSysDuty.getClasses())
                .eq("name", tSysDuty.getName())
                .eq("dept_name", tSysDuty.getDeptName())
                .eq("phone", tSysDuty.getPhone())
                .eq("company_name", tSysDuty.getCompanyName())
//                .eq("tenant_name", tSysDuty.getTenantName())
                .select("id", "name");
        TSysDuty one = this.getOne(queryWrapper);
        Person person = new Person();
        if (one != null) {
            person.setId(one.getId());
            person.setName(one.getName());
        } else {
            this.save(tSysDuty);
            person.setId(id);
            person.setName(name);
        }
        return person;
    }

    public Date parseDate(String date) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Date parse = null;
        try {
            parse = format.parse(date);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return parse;
    }

    @Override
    public BaseResponse<List<Duty>> getDutyList(String id) throws Exception {
        TSysDutyMonth one = tSysDutyMonthService.getById(id);
        if (one == null) {
            throw new BusinessException("该月没有数据");
        }
        QueryWrapper<TSysDuty> tSysDutyQueryWrapper = new QueryWrapper<>();
        tSysDutyQueryWrapper.in("ref_id", one.getId());
        tSysDutyQueryWrapper.eq("status", "0");
        tSysDutyQueryWrapper.orderByAsc("sort");
        List<TSysDuty> list = this.list(tSysDutyQueryWrapper);
        //按天返回整月数据，不对班次进行分组
        List<Duty> duties = returnPersonDay(list, one);
        duties.stream().forEach(item -> {
            String createBy = item.getCreateBy();
            SysUser byId = sysUserService.getById(createBy);
            item.setCreateBy(byId.getUserName());
        });
        BaseResponse<List<Duty>> response = new BaseResponse<>();
        response.setData(duties);
        return response;
    }

    @Override
    public BaseResponse deleteDuty(String id) {
        BaseResponse<Object> response = new BaseResponse<>();
        TSysDutyMonth service = tSysDutyMonthService.getById(id);
        tSysDutyMonthService.removeById(id);
        List<TSysDuty> personList =
                dutyService.list(
                        new QueryWrapper<TSysDuty>().lambda().like(TSysDuty::getRefId, service.getId()));
        for (TSysDuty tSysDuty : personList) {
            this.removeById(tSysDuty.getId());
        }
        return response;
    }

    @Override
    public BaseResponse<List<TSysDuty>> getHomeDuty(String orgId) {
        BaseResponse<List<TSysDuty>> baseResponse = new BaseResponse<>();
        LocalDate now = LocalDate.now();
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        String format = now.format(dateTimeFormatter);
        QueryWrapper<TSysDuty> wrapper = new QueryWrapper<>();
        if (StringHelper.isEmpty(orgId)) {
            String rule = sysRuleService.dataRuleScope(DefaultRule.SHOU_YE.name());
            if (StringUtils.isNotEmpty(rule)) {
                wrapper.apply(rule);
            }
        } else {
            List<String> list = tLeaseBankController.getSubordinate(orgId);
            wrapper.in("company_id", list);
        }
        wrapper.eq("duty_date", format);
        List<TSysDuty> list = this.list(wrapper);
        List<TSysDuty> resultList = new ArrayList<>();
        for (TSysDuty tSysDuty : list) {
            String userId = tSysDuty.getUserId();
            SysUser sysUser = sysUserService.getById(userId);
            if (ObjectHelper.isNotEmpty(sysUser)) {
                String userName = sysUser.getUserName();
                tSysDuty.setUserId(userName);
            }
            //去判断审核是否通过
            TSysDutyMonth tSysDutyMonth = tSysDutyMonthService.getOne(new QueryWrapper<TSysDutyMonth>().eq("id", tSysDuty.getRefId()));
            if (tSysDutyMonth != null) {
                //如果审核通过
                if (tSysDutyMonth.getProcessStatus().equals("5")) {
                    resultList.add(tSysDuty);
                }
            }
        }
        baseResponse.setData(resultList);
        return baseResponse;
    }

    @SneakyThrows
    @Override
    public List<ExportPo> downloadDutyLog(TSysDutyMonth tSysDutyMonth) {
        List<ExportPo> exportPos = new ArrayList<>();
        tSysDutyMonth.setType("2");
        List<Duty> data = this.getLists(tSysDutyMonth).getData();
        data = data.stream().sorted(Comparator.comparing(p -> p.getDutyDate())).collect(Collectors.toList());
        for (Duty datum : data) {
            List<Person> personList = datum.getPersonList();
            personList = personList.stream().sorted(Comparator.comparing(p -> p.getClasses())).collect(Collectors.toList());
            if (personList != null) {
                for (Person person : personList) {
                    ExportPo exportPo = new ExportPo();
                    //机构名称
                    exportPo.setOrgName(datum.getCompanyName());
                    //机构编号
                    SysOrg byId = sysOrgService.getById(datum.getCompanyId());
                    if (byId != null) {
                        exportPo.setOrgNumber(byId.getOrgCode());
                    }
                    //年月日
                    LocalDate localDate = LocalDate.parse(datum.getDutyDate());
                    // 获取年、月、日
                    int yearResult = localDate.getYear();
                    int monthResult = localDate.getMonthValue();
                    int dayResult = localDate.getDayOfMonth();
                    exportPo.setYear(yearResult);
                    exportPo.setMonth(monthResult);
                    exportPo.setDay(dayResult);
                    //设置值班模式
                    exportPo.setDutyMode(datum.getDutyPattern());
                    //班次
                    exportPo.setShift(person.getClasses());
                    String dutyTime = datum.getLateTime();
                    if("全天".equals(person.getClasses()) && StringUtils.isNotBlank(datum.getAllTime())){
                        dutyTime = datum.getAllTime();
                    } else if("早班".equals(person.getClasses()) && StringUtils.isNotBlank(datum.getMorTime())){
                        dutyTime = datum.getMorTime();
                    }
                    //开始时间 结束时间 日期
                    DutyDate dutyDate = JSONObject.parseObject(dutyTime, DutyDate.class);
                    if (dutyDate != null) {
                        exportPo.setStartTime(dutyDate.getStartTime());
                        exportPo.setEndTime(dutyDate.getEndTime());
                        String isNextDay = dutyDate.getIsNextDay();
                        if (isNextDay.equals("1")) {
                            exportPo.setDate("当日");
                        } else {
                            exportPo.setDate("次日");
                        }
                    }
                    //部门
                    exportPo.setDepartment(person.getDeptName());
                    //值班人员
                    exportPo.setDutyPersonnel(person.getName());
                    //AD账号
                    SysUser sysUser = sysUserService.getById(person.getUserId());
                    if (sysUser != null) {
                        exportPo.setAdAccount(sysUser.getLoginName());
                        //职务
                        exportPo.setPostName(sysUser.getPostName());
                        //联系电话
                        exportPo.setPhone(sysUser.getPhoneNo());
                    }
                    exportPos.add(exportPo);
                }
            }
        }
        return exportPos;
    }

    @SneakyThrows
    @Override
    public void exportDuty(TSysDutyMonth tSysDutyMonth, HttpServletResponse response) {
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        String fileName = URLEncoder.encode("值班表", "utf-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName+ DateUtils.dateTimeNow() + ".xlsx");
        response.addHeader("Pargam", "no-cache");
        response.addHeader("Cache-Control", "no-cache");

        // 获取模板文件的输入流
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("excel/zbbdcmb.xlsx");

        // 通过 POI 创建 Workbook 对象
        XSSFWorkbook workbook = new XSSFWorkbook(inputStream);

        // sheet 名-数据对象
        Map<String, List<ExportDutyPo>> sheetMap = buildExport(tSysDutyMonth.getDutyDate());

        // 遍历复制 sheet
        int sheetNo = 0;
        for (String key : sheetMap.keySet()) {
            workbook.cloneSheet(sheetNo, key);
            sheetNo++;
        }

        // 移除原始模板 sheet
        workbook.removeSheetAt(0);

        // 写到 ByteArrayOutputStream
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        workbook.write(bos);
        workbook.close();

        // 创建模板输入流
        ByteArrayInputStream is = new ByteArrayInputStream(bos.toByteArray());

        int[] index = {1,2,3,4,9};
        int rwoIndex = 2;
        ExcelFillCellMergeStrategyUtils excelFillCellMergeStrategyUtils = new ExcelFillCellMergeStrategyUtils(rwoIndex,index);


        // 创建 EasyExcel 的写入对象
        ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).withTemplate(is).registerWriteHandler(excelFillCellMergeStrategyUtils).build();
        // 遍历填充详情数据
        final int[] sheetNumber = {0};
        sheetMap.entrySet().forEach(entry -> {
            String sheetName = entry.getKey();
            List<ExportDutyPo> data = entry.getValue();
            // 创建新的 WriteSheet，确保每个 sheet 从头开始填充
            WriteSheet writeSheet = EasyExcel.writerSheet(sheetName).sheetNo(sheetNumber[0]).build();

            // 填充数据
            excelWriter.fill(data, writeSheet);
            Map<String, Object> map = new HashMap<>();
            map.put("date", sheetName);
            excelWriter.fill(map,writeSheet);
            sheetNumber[0]++;
        });

        // 关闭 ExcelWriter 对象
        excelWriter.finish();

    }

    @Override
    public BaseResponse<TSysDutyMonth> getDutyMonth(String id) {
        BaseResponse<TSysDutyMonth> response = new BaseResponse<>();
        TSysDutyMonth byId = tSysDutyMonthService.getById(id);
        response.setData(byId);
        return response;
    }


    private Map<String, List<ExportDutyPo>> buildExport(String dutyDate){
        UserInfo loginUser = ContextUtils.getLoginUser();
        String orgId = loginUser.getOrgId();
        NewSysOrg byId = newSysOrgService.getById(orgId);
        List<String> orgIds = new ArrayList<>();
        String parentId = byId.getParentId();
        orgIds.addAll(newSysOrgService.getIdsChildrenById(orgId));
        //如果父级id不为0
        if (StringUtils.isNotBlank(parentId) && !parentId.equals("0")) {
            orgIds.add(parentId);
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate firstDayOfMonth = LocalDate.parse(dutyDate + "-01", formatter);
        // 获取当前月的最后一天
        LocalDate lastDayOfMonth = firstDayOfMonth.with(TemporalAdjusters.lastDayOfMonth());
        LocalDate currentDay = firstDayOfMonth;
        //sheet名-数据对象
        Map<String, List<ExportDutyPo>> sheetMap = new LinkedHashMap<>();
        while (!currentDay.isAfter(lastDayOfMonth)) {
            List<ExportDutyPo> exportDutyPos = new ArrayList<>();
            //获取值班信息
            List<TSysDuty> tSysDuties = this.list(new LambdaQueryWrapper<TSysDuty>()
                    .in(TSysDuty::getCompanyId, orgIds)
                    .like(TSysDuty::getDutyDate, currentDay).orderByAsc(TSysDuty::getCompanyId,TSysDuty::getClasses)
            );
            int number = 1;
            for (TSysDuty tSysDuty : tSysDuties) {
                ExportDutyPo exportDutyPo = new ExportDutyPo();
                exportDutyPo.setClasses(tSysDuty.getClasses());
                String companyId = tSysDuty.getCompanyId();
                SysOrgVo sysOrgVo = newSysOrgService.lookOrg(companyId);
                String path = sysOrgVo.getPath();
                String[] split = path.split("/");
                exportDutyPo.setLevelOne(split.length > 0 ? split[0] : "-");
                exportDutyPo.setLevelTwo(split.length > 1 ? split[1] : "-");
                exportDutyPo.setLevelThree(split.length > 2 ? split[2] : "-");
                exportDutyPo.setLevelFour(split.length > 3 ? split[3] : "-");
                SysUser sysUser = sysUserService.getById(tSysDuty.getUserId());
                if (sysUser != null) {
                    exportDutyPo.setNumber(number);
                    exportDutyPo.setUserName(sysUser.getUserName());
                    exportDutyPo.setPhone(sysUser.getPhoneNo());
                    String postId = sysUser.getPostId();
                    TSysPost tSysPost = sysPostService.getById(postId);
                    if (tSysPost != null) {
                        exportDutyPo.setPositionName(tSysPost.getPostName());
                    }
                    TSysDutyLog tSysDutyLog = sysDutyLogService.getOne(new LambdaQueryWrapper<TSysDutyLog>()
                            .eq(TSysDutyLog::getDutyDate, tSysDuty.getDutyDate())
                            .eq(TSysDutyLog::getCompanyId, companyId)
                            .like(TSysDutyLog::getClasses,tSysDuty.getClasses())
                    );
                    //获取值班人数
                    int count = this.count(new LambdaQueryWrapper<TSysDuty>()
                            .eq(TSysDuty::getDutyDate, tSysDuty.getDutyDate())
                            .eq(TSysDuty::getCompanyId, companyId)
                            .eq(TSysDuty::getClasses, tSysDuty.getClasses())
                    );
                    //如果值班日志不为空
                    if (tSysDutyLog != null) {
                        String[] jobIds = tSysDutyLog.getJobId().split(",");
                        //获取作业活动
                        List<TSysTaskWork> taskWorks = tSysTaskWorkService.list(new LambdaQueryWrapper<TSysTaskWork>().in(TSysTaskWork::getId, jobIds));
                        if (taskWorks != null && taskWorks.size() > 0) {
                            for (TSysTaskWork taskWork : taskWorks) {
                                ExportDutyPo exportDutyPo1 = exportDutyPo;
                                exportDutyPo1.setContent(taskWork.getContent());
                                exportDutyPo1.setToll(String.valueOf(count));
                                String involvePerson = taskWork.getInvolvePerson();
                                if (StringUtils.isNotBlank(involvePerson)) {
                                    String[] involvePersons = involvePerson.split(",");
                                    exportDutyPo1.setPartiesInvolved(String.valueOf(involvePersons.length));
                                }
                                exportDutyPos.add(exportDutyPo1);
                            }
                        } else {
                            exportDutyPos.add(exportDutyPo);
                        }
                    }else {
                        exportDutyPos.add(exportDutyPo);
                    }
                }
                number ++;
            }
            if (tSysDuties != null && tSysDuties.size() > 0) {
                putIfContainsKey(sheetMap,currentDay.toString(),exportDutyPos);
            }
            currentDay = currentDay.plusDays(1);
        }
        return sheetMap;
    }


    public static void putIfContainsKey(Map sheetMap, String sheetName, Object data) {
        if(sheetMap.containsKey(sheetName)){
            putIfContainsKey(sheetMap, sheetName + "(1)", data);
        }else {
            sheetMap.put(sheetName, data);
        }
    }


}
