package org.dromara.zjk.service.impl;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.apache.dubbo.config.annotation.DubboReference;
import org.dromara.common.core.constant.UserConstants;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.resource.api.RemoteMessageService;
import org.dromara.system.api.RemoteDictService;
import org.dromara.system.api.RemoteUserService;
import org.dromara.system.api.domain.vo.RemoteRoleVo;
import org.dromara.system.api.model.LoginUser;
import org.dromara.zjk.domain.*;
import org.dromara.zjk.domain.bo.ZjkLeaveBo;
import org.dromara.zjk.domain.dto.CreditInfoDto;
import org.dromara.zjk.domain.dto.LeaveRankDto;
import org.dromara.zjk.domain.dto.LeaveStsDto;
import org.dromara.zjk.domain.vo.*;
import org.dromara.zjk.enums.ApprovalProcessBusinessTypeEnum;
import org.dromara.zjk.enums.ApprovalProcessTypeEnum;
import org.dromara.zjk.enums.ApprovalStatusEnum;
import org.dromara.zjk.enums.LeaveStatusEnum;
import org.dromara.zjk.mapper.*;
import org.dromara.zjk.service.IZjkApprovalProcessLogsService;
import org.dromara.zjk.service.IZjkLeaveService;
import org.dromara.zjk.utils.DateRangUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

/**
 * 【请填写功能名称】Service业务层处理
 *
 * @author ygh
 * @date 2024-10-30
 */
@RequiredArgsConstructor
@Service
public class ZjkLeaveServiceImpl implements IZjkLeaveService {

    private final ZjkLeaveMapper baseMapper;
    private final ZjkLeaveRuleMapper zjkLeaveRuleMapper;
    private final ScheduledExecutorService scheduledExecutorService;
    @DubboReference
    private final RemoteMessageService remoteMessageService;
    private final ZjkCreditRuleMapper zjkCreditRuleMapper;
    private final ZjkExpertMapper zjkExpertMapper;
    private final ZjkReviewPhaseMapper zjkReviewPhaseMapper;
    private final ZjkExpertItemMapper zjkExpertItemMapper;
    private final ZjkItemExtreationMapper zjkItemExtreationMapper;

    @Resource
    private ApplicationEventPublisher eventPublisher;
    @DubboReference(timeout = 20000)
    private RemoteDictService remoteDictService;
    @DubboReference(timeout = 20000)
    private RemoteUserService remoteUserService;

    private final IZjkApprovalProcessLogsService zjkApprovalProcessLogsService;


    /**
     * 查询【请填写功能名称】
     *
     * @param gid 主键
     * @return 【请填写功能名称】
     */
    @Override
    public ZjkLeaveVo queryById(String gid) {

        ZjkLeaveVo zjkLeaveVo = baseMapper.selectLeaveSpDetail(gid);
        List<ZjkLeaveVo> zjkLeaveVos = Arrays.asList(zjkLeaveVo);
//        setTrans(zjkLeaveVos);
        return zjkLeaveVos.get(0);
    }

    /**
     * 分页查询【请填写功能名称】列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 【请填写功能名称】分页列表
     */
    @Override
    public TableDataInfo<ZjkLeaveVo> queryPageList(ZjkLeaveBo bo, PageQuery pageQuery) {
        Long userId = LoginHelper.getUserId();
        bo.setCreateBy(userId);
        IPage<ZjkLeaveVo> result = baseMapper.selectPageAdminLeaveList(pageQuery.build(), bo);
       // setTrans(result.getRecords());
        return TableDataInfo.build(result);
    }

    private void setTrans(List<ZjkLeaveVo> result) {
        result.stream().forEach(item -> {
            if (item.getStatus() != null) {
                item.setStatus(remoteDictService.getTransByTypeAndValue(UserConstants.APPROVAL_STATUS, item.getStatus()));
            }
            if (item.getLeaveType() != null) {
                item.setLeaveType(remoteDictService.getTransByTypeAndValue(UserConstants.LEAVE_TYPE, item.getLeaveType()));
            }
        });
    }


    /**
     * 查询符合条件的【请填写功能名称】列表
     *
     * @param bo 查询条件
     * @return 【请填写功能名称】列表
     */
    @Override
    public List<ZjkLeaveVo> queryList(ZjkLeaveBo bo) {
        LambdaQueryWrapper<ZjkLeave> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<ZjkLeave> buildQueryWrapper(ZjkLeaveBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<ZjkLeave> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getGid()), ZjkLeave::getGid, bo.getGid());
        lqw.eq(StringUtils.isNotBlank(bo.getLeaveType()), ZjkLeave::getLeaveType, bo.getLeaveType());
        lqw.eq(bo.getStartDate() != null, ZjkLeave::getStartDate, bo.getStartDate());
        lqw.eq(bo.getEndDate() != null, ZjkLeave::getEndDate, bo.getEndDate());
        lqw.eq(bo.getLeaveDays() != null, ZjkLeave::getLeaveDays, bo.getLeaveDays());
        lqw.eq(StringUtils.isNotBlank(bo.getLeaveReason()), ZjkLeave::getLeaveReason, bo.getLeaveReason());
        lqw.eq(bo.getStatus() != null, ZjkLeave::getStatus, bo.getStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getApprovalUser()), ZjkLeave::getApprovalUser, bo.getApprovalUser());
        lqw.eq(StringUtils.isNotBlank(bo.getApprovalMsg()), ZjkLeave::getApprovalMsg, bo.getApprovalMsg());
        return lqw;
    }

    /**
     * 新增【请填写功能名称】
     *
     * @param bo 【请填写功能名称】
     * @return 是否新增成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<Void> insertByBo(ZjkLeaveBo bo) {
        //只有是专家角色才能进行专家请假
        LoginUser loginUser = LoginHelper.getLoginUser();
        List<RemoteRoleVo> remoteRoleVos = remoteUserService.selectRolesByUserId(loginUser.getUserId());
        if (!checkIsZj(remoteRoleVos)) {
            return R.fail("专家角色才能进行请假");
        }

        //请假校验
        ZjkLeaveRuleVo zjkLeaveRuleVo = zjkLeaveRuleMapper.selectRuleByTannet(loginUser.getTenantId());
        if(zjkLeaveRuleVo==null){
            return R.fail("请假规则未配置，请联系管理员");

        }
        long betweenDays = DateUtil.between(bo.getStartDate(), new Date(), DateUnit.DAY);
        if (betweenDays < Long.valueOf(zjkLeaveRuleVo.getBeforeDay())) {
            return R.fail("请提前" + zjkLeaveRuleVo.getBeforeDay() + "天进行请假");
        }

        //请假未通过时不可重复发起请假
//        Boolean rangeFlag = false;
//        ZjkLeaveVo rangevo = zjkLeaveRuleMapper.checkLeaveRange(loginUser.getUserId());
//        if (rangevo != null) {
//            rangeFlag = checkTimesHasOverlap(rangevo.getStartDate(), rangevo.getEndDate(), bo.getStartDate(), bo.getEndDate());
//
//        }
//        if (rangeFlag) {
//            return R.fail("有未通过的请假与本次请假时间有重叠，不能重复提交请假");
//        }
        //请假时长做限制
        long qjDays = DateUtil.between(bo.getEndDate(), bo.getStartDate(), DateUnit.DAY);
        if (qjDays > zjkLeaveRuleVo.getLeaveDay()) {
            return R.fail("请提天数不允许超过" + zjkLeaveRuleVo.getLeaveDay() + "天");
        }
        //已接受状态下，需先进行项目请假
        List<ZjkEvaluateVO> result = baseMapper.getLeavePros(loginUser.getUserId(), null);
        if (!CollectionUtils.isEmpty(result)) {
            AtomicBoolean flag = new AtomicBoolean(true);
            result.stream().forEach(item -> {
                String acceptStatus = item.getAcceptStatus();
                Date psTime = item.getReviewTime();
                if (psTime.after(bo.getStartDate()) && psTime.before(bo.getEndDate())) {
                    //评审时间在请假期间内
                    if (UserConstants.APPROVAL_STATUS_AGREE.equals(acceptStatus)) {
                        //已接受情况，直接返回信息
                        flag.set(false);
                    } else {
                        //未接受情况下，更新请假状态，更新请假实际抽取到的人数
                        //对已入库，未接受的专家，如果请假后更新该专家的请假状态
                        //更新入库表的请假状态
                        List<Long> ruleIds = baseMapper.getRuleIdsByItemId(item.getItemId(), item.getItemStage());
                        if (!CollectionUtils.isEmpty(ruleIds)) {
                            baseMapper.updateLeaveStatusRangeTime(loginUser.getUserId(), ruleIds);
                            //更新实抽人数减一
                            baseMapper.updateExtraUserNum(ruleIds);
                        }

                    }
                }
            });
            if (!flag.get()) {
                return R.fail("有待参评的项目，请先进行项目请假");

            }
        }
        ZjkLeave add = MapstructUtils.convert(bo, ZjkLeave.class);
        add.setCreateBy(loginUser.getUserId());
        add.setCreateDept(loginUser.getDeptId());
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setGid(add.getGid());
        }
        // 审批流程记录
        zjkApprovalProcessLogsService.saveCommonApprovalRecord(ApprovalProcessTypeEnum.APPROVAL_INITIATED.getCode(),
            ApprovalProcessBusinessTypeEnum.LEAVE.getCode(),
            null);

        return R.ok();
    }

    /**
     * 判断两个时间范围是否有交集
     *
     * @param dynaStartTime  比较时间段开始时间
     * @param dynaEndTime    比较时间段结束时间
     * @param fixedStartTime 参考时间段开始时间
     * @param fixedEndTime   参考时间段结束时间
     * @return
     */
    public static Boolean checkTimesHasOverlap(Date dynaStartTime, Date dynaEndTime, Date fixedStartTime, Date fixedEndTime) {
        if (dynaStartTime.getTime() <= fixedStartTime.getTime() && dynaEndTime.getTime() > fixedStartTime.getTime()) {
            return true;
        } else if (dynaStartTime.getTime() >= fixedStartTime.getTime() && dynaStartTime.getTime() < fixedEndTime.getTime()) {
            return true;
        } else {
            return false;
        }
    }

    private boolean checkIsZj(List<RemoteRoleVo> remoteRoleVos) {
        boolean flag = false;
        if (!CollectionUtils.isEmpty(remoteRoleVos)) {
            for (int i = 0; i < remoteRoleVos.size(); i++) {
                String roleName = remoteRoleVos.get(i).getRoleName();
                if (UserConstants.ROLE_NAME_CN.equals(roleName)) {
                    flag = true;
                    return flag;
                }
            }
        }
        return flag;
    }

    /**
     * 修改【请填写功能名称】
     *
     * @param bo 【请填写功能名称】
     * @return 是否修改成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByBo(ZjkLeaveBo bo) {
        bo.setApprovalUser(String.valueOf(LoginHelper.getUserId()));
        ZjkLeave zjkLeave = baseMapper.selectById(bo.getGid());
        ZjkLeave update = MapstructUtils.convert(bo, ZjkLeave.class);
        String message = null;
        //给批准审批的人发消息
        if (LeaveStatusEnum.SUCCESS.getCode().equals(bo.getStatus())) {
            message = "您的请假申请已审批通过";
        } else if (LeaveStatusEnum.ERROR.getCode().equals(bo.getStatus())) {
            message = "您的请假申请已被驳回";
        }
        if (message != null) {
            String finalMessage = message;
            scheduledExecutorService.schedule(() -> {
                remoteMessageService.publishMessage(Long.valueOf(zjkLeave.getCreateBy()), finalMessage);
            }, 3, TimeUnit.SECONDS);
        }

        // 审批流程记录
        zjkApprovalProcessLogsService.saveCommonApprovalRecord(bo.getStatus().equals(ApprovalStatusEnum.SUCCESS.getCodeAsString()) ? ApprovalProcessTypeEnum.APPROVAL_PASSED.getCode() : ApprovalProcessTypeEnum.APPROVAL_REFUSED.getCode(),
            zjkLeave.getLeaveType().equals("1") ? ApprovalProcessBusinessTypeEnum.LEAVE.getCode() : ApprovalProcessBusinessTypeEnum.APPROVAL_STATUS_NOT_AGREE.getCode(),
            bo.getApprovalMsg());
        return baseMapper.updateById(update) > 0;
    }


    /**
     * 校验并批量删除【请填写功能名称】信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
    }

    @Override
    public TableDataInfo<ZjkLeaveVo> queryPageSpList(ZjkLeaveBo bo, PageQuery pageQuery) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        bo.setTenantId(loginUser.getTenantId());
        IPage<ZjkLeaveVo> result = baseMapper.selectPageSpList(pageQuery.build(), bo);
//        List<ZjkLeaveVo> records = result.getRecords();
//        setTrans(records);

        return TableDataInfo.build(result);
    }

    @Override
    public TableDataInfo<ZjkLeaveVo> queryAdminPageList(ZjkLeaveBo bo, PageQuery pageQuery) {

        IPage<ZjkLeaveVo> result = baseMapper.selectPageAdminLeaveList(pageQuery.build(), bo);
//        setTrans(result.getRecords());
        return TableDataInfo.build(result);
    }

    @Override
    public R<StsNumVO> getStsNum() {
        List<ZjkLeave> zjkLeaves = baseMapper.selectList();
        StsNumVO stsNumVO = new StsNumVO();
        if (!CollectionUtils.isEmpty(zjkLeaves)) {
            Long num = zjkLeaves.stream().count();
            stsNumVO.setNum(num);
            long days = zjkLeaves.stream().mapToLong(item -> {
                long betweenDays = DateUtil.between(item.getEndDate(), item.getStartDate(), DateUnit.DAY);
                return betweenDays;
            }).sum();
            stsNumVO.setDay(days);
            //已批天数
            long ypdays = zjkLeaves.stream().filter(k -> k.getStatus().equals(UserConstants.APPROVAL_STATUS_AGREE)).mapToLong(item -> {
                long betweenDays = DateUtil.between(item.getEndDate(), item.getStartDate(), DateUnit.DAY);
                return betweenDays;
            }).sum();
            stsNumVO.setAgreeDays(ypdays);
            long proNums = zjkLeaves.stream().filter(k -> UserConstants.LEAVE_TYPE_PRO.equals(k.getLeaveType())).count();
            stsNumVO.setProNums(proNums);
        }

        return R.ok(stsNumVO);
    }

    @Override
    public TableDataInfo<ZjkEvaluateVO> getLeavePros() {
        List<ZjkEvaluateVO> result = null;
        LoginUser loginUser = LoginHelper.getLoginUser();
        //TODO 管理员
        List<RemoteRoleVo> remoteRoleVos = remoteUserService.selectRolesByUserId(loginUser.getUserId());
        if (!checkIsZj(remoteRoleVos)) {
            //不是专家角色查询所有
            result = baseMapper.getLeavePros(null, null);
        }
        result = baseMapper.getLeavePros(loginUser.getUserId(), null);
        return TableDataInfo.build(result);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<Void> leaveForPro(ZjkEvaluateVO vo) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        //请假校验
        ZjkLeaveRuleVo zjkLeaveRuleVo = zjkLeaveRuleMapper.selectRuleByTannet(loginUser.getTenantId());
        String proBeforeHour = zjkLeaveRuleVo.getProBeforeHour();
        Date reviewTime = vo.getReviewTime();
        long hours = DateUtil.between(reviewTime, new Date(), DateUnit.HOUR);
        if (hours <= Long.valueOf(proBeforeHour) && vo.getUserId() == null) {
            return R.fail("评审前" + zjkLeaveRuleVo.getBeforeDay() + "小时才能进行请假");
        }
        ZjkLeave zjkLeave = new ZjkLeave();
        zjkLeave.setLeaveType(UserConstants.LEAVE_TYPE_PRO);
        zjkLeave.setLeaveDays(1L);
        zjkLeave.setStatus(UserConstants.APPROVAL_STATUS_AGREE);
        zjkLeave.setStartDate(vo.getReviewTime());
        zjkLeave.setEndDate(vo.getReviewTime());
        zjkLeave.setLeaveReason(vo.getLeaveReason());
        if (vo.getUserId() != null) {
            //管理员代请
            zjkLeave.setCreateBy(Long.valueOf(vo.getUserId()));
            zjkLeave.setCreateDept(remoteUserService.getUserInfo(Long.valueOf(vo.getUserId()),loginUser.getTenantId()).getDeptId());
            zjkLeave.setLeaveResource(1);
        } else {
            zjkLeave.setCreateBy(loginUser.getUserId());
            zjkLeave.setCreateDept(loginUser.getDeptId());

        }
        //插入请假记录
        baseMapper.insert(zjkLeave);
        // 根据用户 id 项目 id 更新专家请假信息
        ZjkExpertItem zjkExpertItem = zjkExpertItemMapper.getExpertItemByUserIdAndItemId(String.valueOf(LoginHelper.getUserId()),vo.getItemId(),vo.getItemStage());
        zjkExpertItem.setLeaveStatus("1");
        zjkExpertItemMapper.updateById(zjkExpertItem);
        // 更新抽取人数
        ZjkReviewPhase zjkReviewPhase = zjkReviewPhaseMapper.selectById(zjkExpertItem.getReviewId());
        ZjkItemExtreation zjkItemExtreation =zjkItemExtreationMapper.selectOne(new LambdaQueryWrapper<ZjkItemExtreation>()
            .eq(ZjkItemExtreation::getId,zjkReviewPhase.getItemExtreationId()));
        if (zjkItemExtreation != null){
            zjkItemExtreation.setExtractedSum(zjkItemExtreation.getExtractedSum()-1);
            zjkItemExtreation.setExtractionStatus(1);
            zjkItemExtreationMapper.updateById(zjkItemExtreation);
        }
//        //更新入库表的请假状态
//        List<Long> ruleIds = baseMapper.getRuleIdsByItemId(vo.getItemId(), vo.getItemStage());
//        baseMapper.updateExpertLeaveStatus(LoginHelper.getLoginUser().getUserId(), vo.getItemId(), ruleIds);
//        //更新实抽人数减一
//        baseMapper.updateExtraUserNum(ruleIds);
        //更新信用分
        //发布完成评价的信用事件
        CreditInfoDto creditInfoDto = new CreditInfoDto();
        //获取信用规则
        LambdaQueryWrapper<ZjkCreditRule> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(ZjkCreditRule::getRuleKey, 2);
        ZjkCreditRuleVo zjkCreditRuleVo = zjkCreditRuleMapper.selectVoOne(lambdaQueryWrapper);
        creditInfoDto.setRuleKey(UserConstants.CREDIT_LEAVE_KEY);
        LambdaQueryWrapper<ZjkExpert> lambdaQueryWrapper1 = new LambdaQueryWrapper();
        lambdaQueryWrapper1.eq(ZjkExpert::getUserId, vo.getUserId()==null?loginUser.getUserId():Long.valueOf(vo.getUserId()));
        ZjkExpertVo zjkExpertVo = zjkExpertMapper.selectVoOne(lambdaQueryWrapper1);
        creditInfoDto.setExpertId(Long.valueOf(zjkExpertVo.getExpertId()));
        creditInfoDto.setCreditSum(zjkCreditRuleVo.getEachScore());
        QueryWrapper<ZjkExpert> wq = new QueryWrapper<>();
        wq.lambda().eq(ZjkExpert::getExpertId, zjkExpertVo.getExpertId());
        ZjkExpert zjkExpert = zjkExpertMapper.selectOne(wq);
        if (zjkExpert != null) {
            creditInfoDto.setUserId(zjkExpert.getUserId());
        }
        eventPublisher.publishEvent(creditInfoDto);
        return R.ok();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<Void> setAccept(ZjkEvaluateVO vo) {
        // 根据用户 id 项目 id 更新专家请假信息
        ZjkExpertItem zjkExpertItem = zjkExpertItemMapper.getExpertItemByUserIdAndItemId(String.valueOf(LoginHelper.getUserId()),vo.getItemId(),vo.getItemStage());
        if (zjkExpertItem.getAcceptStatus().equals("2")) {
            return R.ok();
        }
        zjkExpertItem.setAcceptStatus(vo.getStatus());
        zjkExpertItemMapper.updateById(zjkExpertItem);
        // 专家请假的时候 需要扣减抽取人数
        if (UserConstants.APPROVAL_STATUS_TURN_DOWN.equals(vo.getStatus())){
            // 获取抽取规则
            ZjkReviewPhase zjkReviewPhase = zjkReviewPhaseMapper.selectById(zjkExpertItem.getReviewId());
            if (zjkReviewPhase != null){
                // 更新抽取人数
                ZjkItemExtreation zjkItemExtreation =zjkItemExtreationMapper.selectOne(new LambdaQueryWrapper<ZjkItemExtreation>()
                    .eq(ZjkItemExtreation::getId,zjkReviewPhase.getItemExtreationId()));
                if (zjkItemExtreation != null){
                    zjkItemExtreation.setExtractedSum(zjkItemExtreation.getExtractedSum()-1);
                    zjkItemExtreation.setExtractionStatus(1);
                    zjkItemExtreationMapper.updateById(zjkItemExtreation);
                }
            }
        }
//        //更新入库表的请假状态
//        List<Long> ruleIds = baseMapper.getRuleIdsByItemId(vo.getItemId(), vo.getItemStage());
//        if (!CollectionUtils.isEmpty(ruleIds)) {
//            baseMapper.updateExpertAcceptStatus(LoginHelper.getLoginUser().getUserId(), vo.getItemId(), ruleIds, vo.getStatus());
//            if (UserConstants.APPROVAL_STATUS_TURN_DOWN.equals(vo.getStatus())) {
//                //更新实抽人数减一
//                baseMapper.updateExtraUserNum(ruleIds);
//            }
//        }
        return R.ok();
    }

    private List<String> getYdataByMonth(Map<Integer, Long> data, List<String> monthsRange) {
        List<String> res = new ArrayList<>();
        for (int i = 0; i < monthsRange.size(); i++) {
            String s = monthsRange.get(i).split("月")[0];
            res.add(String.valueOf(data.get(Integer.valueOf(s))));
        }
        return res;
    }

    @Override
    public R<StsLeaveVO> getStsChart(Integer rangeMonth) {
        Date daysAgo = DateUtil.offsetDay(new Date(), -rangeMonth * 30 + 1);
        List<String> monthsRange = DateRangUtils.getMonthsRange(rangeMonth);
        QueryWrapper<ZjkLeave> wq = new QueryWrapper<>();
        wq.lambda().between(ZjkLeave::getCreateTime, daysAgo, new Date()).eq(ZjkLeave::getStatus, LeaveStatusEnum.SUCCESS.getCode());
        List<ZjkLeave> zjkLeaves = baseMapper.selectList(wq);
        StsLeaveVO res = new StsLeaveVO();
        if (!CollectionUtils.isEmpty(zjkLeaves)) {
            //请假次数统计
            Map<Integer, Long> numTotals = zjkLeaves.stream()
                .collect(Collectors.groupingBy(
                    item -> DateUtil.month(item.getCreateTime())+1, // 使用月份作为key
                    Collectors.counting() // 累加数量
                ));
            List<String> numsSts = getYdataByMonth(numTotals, monthsRange);
            //请假天数统计-已经审批同意
            Map<Integer, Long> dayTotals = zjkLeaves.stream()
                .collect(Collectors.groupingBy(
                    item -> DateUtil.month(item.getCreateTime())+1, // 使用月份作为key
                    Collectors.summingLong(
                        leave -> DateUtil.between(leave.getEndDate(), leave.getStartDate(), DateUnit.DAY)
                    )// 累加数量
                ));
            List<String> daysSts = getYdataByMonth(dayTotals, monthsRange);


            //按月分组统计请假人数统计
            List<LeaveStsDto> leaveCs = baseMapper.getLeavePerSts(daysAgo, new Date());
            Map<Integer, Long> percsSts = leaveCs.stream().collect(Collectors.toMap(LeaveStsDto::getMt, LeaveStsDto::getCs));
            List<String> csSts = getYdataByMonth(percsSts, monthsRange);
            //项目请假次数统计
            Map<Integer, Long> xmTotals = zjkLeaves.stream().filter(item -> UserConstants.LEAVE_TYPE_PRO.equals(item.getLeaveType()))
                .collect(Collectors.groupingBy(
                    item -> DateUtil.month(item.getCreateTime())+1, // 使用月份作为key
                    Collectors.counting() // 累加数量
                ));
            List<String> xmSts = getYdataByMonth(xmTotals, monthsRange);


            //审批情况概览
            List<LeaveStsDto> pso = baseMapper.getApprovalStu(daysAgo, new Date());
            StsPreVO stsPreVO = new StsPreVO();
            pso.stream().forEach(item -> {
                if (item.getMt().equals(Integer.valueOf(LeaveStatusEnum.SUCCESS.getCode()))) {
                    stsPreVO.setAgreeNum(Math.toIntExact(item.getCs()));
                } else if (item.getMt().equals(Integer.valueOf(LeaveStatusEnum.APPROVAL.getCode()))) {
                    stsPreVO.setWaitNum(Math.toIntExact(item.getCs()));
                } else if (item.getMt().equals(Integer.valueOf(LeaveStatusEnum.ERROR.getCode()))) {
                    stsPreVO.setRejectNum(Math.toIntExact(item.getCs()));
                }
            });
            //专家请假人员统计
            List<LeaveRankDto> leaveRanks = baseMapper.getLeaveRanks(daysAgo, new Date());
            List<String> names = leaveRanks.stream().map(LeaveRankDto::getExpertName).collect(Collectors.toList());
            List<String> collect = leaveRanks.stream().map(item -> String.valueOf(item.getNums())).collect(Collectors.toList());
            StsChartVO pertj = StsChartVO.builder().xLine(collect).yLine(names).build();

            //按月统计数据汇总
            StsChartVO nums = StsChartVO.builder().xLine(monthsRange).yLine(numsSts).build();
            StsChartVO days = StsChartVO.builder().xLine(monthsRange).yLine(daysSts).build();
            StsChartVO css = StsChartVO.builder().xLine(monthsRange).yLine(csSts).build();
            StsChartVO xms = StsChartVO.builder().xLine(monthsRange).yLine(xmSts).build();
            res.setApprovalSts(stsPreVO);
            res.setNumsSts(nums);
            res.setDaysSts(days);
            res.setPersSts(css);
            res.setProsSts(xms);
            res.setWhoSts(pertj);

        }

        return R.ok(res);
    }

    @Override
    public TableDataInfo<ZjkEvaluateVO> getProsForAccept() {
        List<ZjkEvaluateVO> result = null;
        LoginUser loginUser = LoginHelper.getLoginUser();
        //TODO 管理员
        List<RemoteRoleVo> remoteRoleVos = remoteUserService.selectRolesByUserId(loginUser.getUserId());
        if (!checkIsZj(remoteRoleVos)) {
            //不是专家角色查询所有
            result = baseMapper.getLeavePros(null, 0);
        }
        result = baseMapper.getLeavePros(loginUser.getUserId(), 0);
        return TableDataInfo.build(result);
    }

    @Override
    public TableDataInfo<ZjkEvaluateVO> getProsForJoin() {
        List<ZjkEvaluateVO> result = null;
        LoginUser loginUser = LoginHelper.getLoginUser();
        //TODO 管理员
        List<RemoteRoleVo> remoteRoleVos = remoteUserService.selectRolesByUserId(loginUser.getUserId());
        if (!checkIsZj(remoteRoleVos)) {
            //不是专家角色查询所有
            result = baseMapper.getLeavePros(null, 1);
        }
        result = baseMapper.getLeavePros(loginUser.getUserId(), 1);
        return TableDataInfo.build(result);
    }
}
