package com.usky.iot.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.datascope.annotation.DataScope;
import com.ruoyi.common.datascope.context.DataScopeContextHolder;
import com.usky.common.core.bean.CommonPage;
import com.usky.common.core.exception.BusinessException;
import com.usky.common.mybatis.core.AbstractCrudService;
import com.usky.common.security.utils.SecurityUtils;
import com.usky.iot.domain.PmProject;
import com.usky.iot.domain.PmReceive;
import com.usky.iot.domain.PmWorkContent;
import com.usky.iot.domain.PmWorkReport;
import com.usky.iot.mapper.*;
import com.usky.iot.service.PmWorkContentService;
import com.usky.iot.service.vo.*;
import com.usky.system.domain.SysUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 工作内容表 服务实现类
 * </p>
 *
 * @author fu
 * @since 2024-05-20
 */
@Slf4j
@Service
public class PmWorkContentServiceImpl extends AbstractCrudService<PmWorkContentMapper, PmWorkContent> implements PmWorkContentService {

    @Autowired
    private PmWorkReportMapper pmWorkReportMapper;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private PmReceiveMapper pmReceiveMapper;

    @Autowired
    private PmWorkContentMapper pmWorkContentMapper;

    @Autowired
    private PmProjectMapper pmProjectMapper;

    /**
     * @description: 删除报告内容
     * @author: fu
     * @date: 2024/8/7 17:48
     * @param: [reportId]
     * @return: void
     **/
    @Override
    public void deleteContent(Integer reportId) {
        LambdaQueryWrapper<PmWorkContent> deleteWrapper = Wrappers.lambdaQuery();
        deleteWrapper.eq(PmWorkContent::getReportId, reportId);
        baseMapper.delete(deleteWrapper);
    }

    /**
     * @description: 查询报告id时间段
     * @author: fu
     * @date: 2024/8/7 17:48
     * @param: [startDate, endDate]
     * @return: java.util.List<java.lang.Integer>
     **/
    private List<Integer> reportDateQuery(String startDate, String endDate) {
        Long deptId = SecurityUtils.getLoginUser().getSysUser().getDeptId();
        Integer tenantId = SecurityUtils.getTenantId();
        LambdaQueryWrapper<PmWorkReport> reportQuery = Wrappers.lambdaQuery();
        reportQuery.select(PmWorkReport::getId).eq(PmWorkReport::getTenantId, tenantId).eq(PmWorkReport::getDeptId, deptId);
        if (StringUtils.isNotBlank(startDate) && StringUtils.isNotBlank(endDate)) {
            LocalDate start = null;
            LocalDate end = null;
            try {
                start = LocalDate.parse(startDate);
                end = LocalDate.parse(endDate);
            } catch (Exception e) {
                log.error("时间格式错误：", e);
                throw new BusinessException("时间格有误，请重新输入");
            }
            reportQuery.between(PmWorkReport::getReportDate, start, end);
        }
        List<PmWorkReport> reportIds = pmWorkReportMapper.selectList(reportQuery);
        List<Integer> rIds = new ArrayList<>();
        for (PmWorkReport report : reportIds) {
            rIds.add(report.getId());
        }
        return rIds;
    }

    /**
     * @description: 查询我收到的报告
     * @author: fu
     * @date: 2024/8/7 17:48
     * @param: []
     * @return: java.util.List<java.lang.Integer>
     **/
    private List<Integer> receive() {
        Long userId = SecurityUtils.getUserId();
        Integer tenantId = SecurityUtils.getTenantId();
        LambdaQueryWrapper<PmWorkReport> reportQuery = Wrappers.lambdaQuery();
        reportQuery.select(PmWorkReport::getId)
                .eq(PmWorkReport::getTenantId, tenantId)
                .apply("FIND_IN_SET(" + userId + ", cc_to) > 0")
                .orderByDesc(PmWorkReport::getReportDate);
        return pmWorkReportMapper.selectList(reportQuery).stream().map(PmWorkReport::getId).collect(Collectors.toList());
    }

    /**
     * @description: 查询我发出的报告
     * @author: fu
     * @date: 2024/8/7 17:48
     * @param: []
     * @return: java.util.List<java.lang.Integer>
     **/
    private List<Integer> sentOut() {
        Long userid = SecurityUtils.getUserId();
        LambdaQueryWrapper<PmWorkReport> reportQuery = Wrappers.lambdaQuery();
        reportQuery.select(PmWorkReport::getId).eq(PmWorkReport::getSubmitterId, userid).orderByDesc(PmWorkReport::getSubmitDate);
        return pmWorkReportMapper.selectList(reportQuery).stream().map(PmWorkReport::getId).collect(Collectors.toList());
    }

    /**
     * @description: 负责人项目id查询
     * @author: fu
     * @date: 2024/8/7 17:14
     * @param: []
     * @return: java.util.List<java.lang.Integer>
     **/
    private List<Integer> head() {
        Long userId = SecurityUtils.getUserId();
        Integer tenantId = SecurityUtils.getTenantId();
        LambdaQueryWrapper<PmProject> projectQuery = Wrappers.lambdaQuery();
        projectQuery.select(PmProject::getId).eq(PmProject::getTenantId, tenantId).eq(PmProject::getProjectHead, userId);
        return pmProjectMapper.selectList(projectQuery).stream().map(PmProject::getId).collect(Collectors.toList());
    }

    /**
     * @description: 查询项目id
     * @author: fu
     * @date: 2024/8/7 17:14
     * @param: []
     * @return: java.util.List<java.lang.Integer>
     **/
    private List<Integer> reportList(String projectName) {
        Integer tenantId = SecurityUtils.getTenantId();
        LambdaQueryWrapper<PmWorkContent> projectQuery = Wrappers.lambdaQuery();
        projectQuery.select(PmWorkContent::getReportId).eq(PmWorkContent::getProjectName, projectName).eq(PmWorkContent::getTenantId, tenantId);
        List<PmWorkContent> projectIds = pmWorkContentMapper.selectList(projectQuery);
        List<Integer> rIds = new ArrayList<>();
        for (PmWorkContent contenReportId : projectIds) {
            rIds.add(contenReportId.getId());
        }
        return rIds;
    }

    /**
     * @description: 查询项目
     * @author: fu
     * @date: 2024/8/7 17:14
     * @param: [projectIds]
     * @return: java.util.List<com.usky.iot.domain.PmProject>
     **/
    @Override
    public List<PmWorkContent> projectQuery(String startDate, String endDate, String projectName, Integer projectAscription, Long submitterId) {
        LocalDateTime startDateTime = null;
        LocalDateTime endDateTime = null;
        LocalDate start = null;
        LocalDate end = null;
        List<PmWorkContent> workContentList = new ArrayList<>();
        List<Integer> reportIds = new ArrayList<>();

        Set<Integer> reportIdsByDate = new HashSet<>();
        Set<Integer> reportIdsBySubmitterId = new HashSet<>();
        Set<Integer> finalReportIds = new HashSet<>();

        if (StringUtils.isNotBlank(startDate) && StringUtils.isNotBlank(endDate)) {
            DateTimeFormatter formatter = null;
            try {
                formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            } catch (Exception e) {
                throw new BusinessException("时间传参格式不正确请重试");
            }
            start = LocalDate.parse(startDate, formatter);
            end = LocalDate.parse(endDate, formatter);
            startDateTime = start.atStartOfDay();
            endDateTime = end.atTime(23, 59, 59);
            LambdaQueryWrapper<PmWorkReport> reportQuery = Wrappers.lambdaQuery();
            reportQuery.select(PmWorkReport::getId).between(PmWorkReport::getSubmitDate, startDateTime, endDateTime);
            reportIdsByDate = pmWorkReportMapper.selectList(reportQuery).stream().map(PmWorkReport::getId).collect(Collectors.toSet());
        }

        if (submitterId != null) {
            LambdaQueryWrapper<PmWorkReport> reportQuery = Wrappers.lambdaQuery();
            reportQuery.select(PmWorkReport::getId).eq(PmWorkReport::getSubmitterId, submitterId);
            reportIdsBySubmitterId = pmWorkReportMapper.selectList(reportQuery).stream().map(PmWorkReport::getId).collect(Collectors.toSet());
        }

        // 取交集
        if (!reportIdsByDate.isEmpty() && !reportIdsBySubmitterId.isEmpty()) {
            finalReportIds.addAll(reportIdsByDate);
            finalReportIds.retainAll(reportIdsBySubmitterId);
        } else if (!reportIdsByDate.isEmpty()) {
            finalReportIds.addAll(reportIdsByDate);
        } else if (!reportIdsBySubmitterId.isEmpty()) {
            finalReportIds.addAll(reportIdsBySubmitterId);
        }
        reportIds = new ArrayList<>(finalReportIds);


        LambdaQueryWrapper<PmWorkContent> contentLambdaQuery = Wrappers.lambdaQuery();
        contentLambdaQuery.select(PmWorkContent::getProjectId);
        switch (projectAscription) {
            case 1:
                List<Integer> headProjects = head();
                if (headProjects.isEmpty()) {
                    return workContentList;
                }
                contentLambdaQuery.in(PmWorkContent::getProjectId, headProjects);
                break;
            case 2:
                List<Integer> receiveList = receive();
                if (receiveList.isEmpty()) {
                    return workContentList;
                }
                contentLambdaQuery.in(PmWorkContent::getReportId, receiveList);
                break;
            case 3:
                List<Integer> sentOutList = sentOut();
                if (sentOutList.isEmpty()) {
                    return workContentList;
                }
                contentLambdaQuery.in(PmWorkContent::getReportId, sentOutList);
                break;
            default:
                throw new BusinessException("查询标识有误");
        }
        if (StringUtils.isNotBlank(projectName)) {
            contentLambdaQuery.like(PmWorkContent::getProjectName, projectName);
        }
        if (!reportIds.isEmpty()) {
            contentLambdaQuery.in(PmWorkContent::getReportId, reportIds);
        }
        contentLambdaQuery.groupBy(PmWorkContent::getProjectId);
        workContentList = pmWorkContentMapper.selectList(contentLambdaQuery);

        List<Integer> workContentIds = workContentList.stream().map(PmWorkContent::getProjectId).distinct().collect(Collectors.toList());
        if (workContentIds.isEmpty()) {
            return workContentList;
        }
        LambdaQueryWrapper<PmProject> projectQuery = Wrappers.lambdaQuery();
        projectQuery.select(PmProject::getId, PmProject::getProjectName).in(PmProject::getId, workContentIds);
        Map<Integer, String> projectNameMap = pmProjectMapper.selectList(projectQuery).stream().collect(Collectors.toMap(PmProject::getId, PmProject::getProjectName));

        workContentList.forEach(workContent -> {
            workContent.setProjectName(projectNameMap.get(workContent.getProjectId()));
        });

        return workContentList;
    }

    /**
     * @description: 报告记录
     * @author: fu
     * @date: 2024/8/7 17:14
     * @param: [projectIds]
     * @return: java.util.List<com.usky.iot.domain.PmProject>
     **/
    @Override
    public List<PmWorkReport> workReportQuery(String startDate, String endDate, String projectName, Integer projectAscription, Integer reportId) {

        LocalDate start = null;
        LocalDate end = null;
        LocalDateTime startDateTime = null;
        LocalDateTime endDateTime = null;
        if (StringUtils.isNotBlank(startDate) && StringUtils.isNotBlank(endDate)) {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            start = LocalDate.parse(startDate, formatter);
            end = LocalDate.parse(endDate, formatter);
            startDateTime = start.atStartOfDay();
            endDateTime = end.atTime(23, 59, 59);
        }

        List<PmWorkReport> reportList = new ArrayList<>();
        List<PmWorkReport> reportList2 = new ArrayList<>();
        List<PmWorkContent> pmWorkContentList = new ArrayList<>();
        List<Long> userIds = new ArrayList<>();
        if (reportId != null && reportId > 0) {
            LambdaQueryWrapper<PmWorkReport> reportQuery = Wrappers.lambdaQuery();
            reportQuery.eq(PmWorkReport::getId, reportId);
            PmWorkReport report = pmWorkReportMapper.selectOne(reportQuery);
            if (report == null) {
                throw new BusinessException("该报告已被删除！");
            }

            LambdaQueryWrapper<PmWorkContent> contentQuery = Wrappers.lambdaQuery();
            contentQuery.select(PmWorkContent::getWorkContent, PmWorkContent::getWorkTime, PmWorkContent::getProjectName).eq(PmWorkContent::getReportId, reportId);
            pmWorkContentList = this.list(contentQuery);
            report.setWorkContents(pmWorkContentList);
            reportList.add(report);
            for (PmWorkReport c : reportList) {
                userIds.add(c.getSubmitterId());
            }
        } else {
            if (projectAscription != 1 && projectAscription != 2 && projectAscription != 3) {
                throw new BusinessException("查询标识有误");
            }
            List<Integer> receiveList2 = receive();
            if (projectAscription == 2 && receiveList2.isEmpty()) {
                return reportList2;
            }
            List<Integer> sentOutList = sentOut();
            if (projectAscription == 3 && sentOutList.isEmpty()) {
                return reportList2;
            }
            List<Integer> headProjects = head();
            if (projectAscription == 1 && headProjects.isEmpty()) {
                return reportList2;
            }
            LambdaQueryWrapper<PmWorkContent> contentLambdaQuery = Wrappers.lambdaQuery();
            contentLambdaQuery.select(PmWorkContent::getReportId, PmWorkContent::getWorkContent, PmWorkContent::getWorkTime, PmWorkContent::getProjectName);

            if (startDateTime != null) {
                contentLambdaQuery.between(PmWorkContent::getCreateTime, startDateTime, endDateTime);
            }
            if (projectAscription == 1) {
                contentLambdaQuery.in(PmWorkContent::getProjectId, headProjects);
            } else if (projectAscription == 2) {
                contentLambdaQuery.in(PmWorkContent::getReportId, receiveList2);
            } else {
                contentLambdaQuery.in(PmWorkContent::getReportId, sentOutList);
            }
            if (StringUtils.isNotBlank(projectName)) {
                List<Integer> list = reportList(projectName);
                contentLambdaQuery.in(PmWorkContent::getReportId, list);
            }
            pmWorkContentList = this.list(contentLambdaQuery);
            if (pmWorkContentList.isEmpty()) {
                return reportList;
            }
            List<Integer> reportIds = new ArrayList<>();
            for (PmWorkContent a : pmWorkContentList) {
                reportIds.add(a.getReportId());
            }
            LambdaQueryWrapper<PmWorkReport> reportQuery = Wrappers.lambdaQuery();
            reportQuery.select(PmWorkReport::getId, PmWorkReport::getCoordinateWork, PmWorkReport::getTomorrowPlan, PmWorkReport::getCcTo, PmWorkReport::getSubmitterId, PmWorkReport::getCreateTime, PmWorkReport::getReportDate).in(PmWorkReport::getId, reportIds).orderByDesc(PmWorkReport::getCreateTime);
            reportList = pmWorkReportMapper.selectList(reportQuery);
            LambdaQueryWrapper<PmReceive> statusQuery = Wrappers.lambdaQuery();
            statusQuery.select(PmReceive::getReportId, PmReceive::getReadFlag).eq(PmReceive::getReceiverId, SecurityUtils.getUserId()).eq(PmReceive::getTenantId, SecurityUtils.getTenantId()).in(PmReceive::getReportId, reportIds);
            List<PmReceive> receiveList = pmReceiveMapper.selectList(statusQuery);
            for (PmWorkReport c : reportList) {
                List<PmWorkContent> contents = new ArrayList<>();
                for (PmWorkContent b : pmWorkContentList) {
                    if (b.getReportId().equals(c.getId())) {
                        contents.add(b);
                    }
                }
                c.setWorkContents(contents);
                if (!receiveList.isEmpty()) {
                    for (PmReceive receive : receiveList) {
                        if (receive.getReportId().equals(c.getId())) {
                            c.setReadFlag(receive.getReadFlag());
                        }
                    }
                }
                userIds.add(c.getSubmitterId());
            }
        }
        List<SysUser> nickNames = nickNames(userIds);
        for (PmWorkReport d : reportList) {
            for (SysUser e : nickNames) {
                if (e.getUserId().equals(d.getSubmitterId())) {
                    d.setCreateBy(e.getNickName());
                }
            }
            List<Long> ids = null;
            if (!d.getCcTo().isEmpty()) {
                ids = Optional.ofNullable(d.getCcTo()).map(ccTo -> Arrays.stream(ccTo.split(",")).map(Long::parseLong).collect(Collectors.toList())).orElse(Collections.emptyList());
            }
            List<SysUser> nickNameList = null;
            if (CollectionUtils.isNotEmpty(ids)) {
                nickNameList = nickNames(ids);
                StringBuilder ccToBuilder = new StringBuilder();
                Set<Long> addedUserIds = new HashSet<>();
                for (Long id : ids) {
                    for (SysUser user : nickNameList) {
                        if (user.getUserId().equals(id) && !addedUserIds.contains(id)) {
                            if (ccToBuilder.length() > 0) {
                                ccToBuilder.append(", ");
                            }
                            ccToBuilder.append(user.getNickName());
                            addedUserIds.add(id);
                            break;
                        }
                    }
                }
                String ccTo = ccToBuilder.toString();
                d.setCcTo(ccTo);
            }
        }
        return reportList;
    }

    /**
     * @description: 用户名、账户名查询
     * @author: fu
     * @date: 2024/8/7 17:28
     * @param: [userIds]
     * @return: java.util.List<com.usky.system.domain.SysUser>
     **/
    @Override
    public List<SysUser> nickNames(List<Long> userIds) {
        LambdaQueryWrapper<SysUser> usersQuery = Wrappers.lambdaQuery();
        usersQuery.select(SysUser::getUserId, SysUser::getNickName, SysUser::getUserName, SysUser::getPhonenumber, SysUser::getAvatar, SysUser::getSex, SysUser::getDeptId)
                .eq(SysUser::getTenantId, SecurityUtils.getTenantId())
                .eq(SysUser::getDelFlag, 0);
        if (!userIds.isEmpty()) {
            usersQuery.in(SysUser::getUserId, userIds);
        }
        return sysUserMapper.selectList(usersQuery);
    }

    /**
     * @description: 报告记录分页
     * @author: fu
     * @date: 2024/8/7 17:28
     * @param: [startDate, endDate, projectName, projectAscription]
     * @return: java.util.List<com.usky.system.domain.PmWorkContent>
     **/
    @Override
    public CommonPage<PmWorkReport> reportPage(Integer projectAscription, Integer pageNum, Integer pageSize, Integer reportId, String startDate,
                                               String endDate, Integer projectId, Long userId, Integer upOrDown, Integer slideSum, String submitDate) {
        if (pageNum < 1 || pageSize < 1) {
            throw new BusinessException("页码和每页数量不能小于1");
        }

        List<PmWorkReport> reportList = new ArrayList<>();
        IPage<PmWorkReport> reportPage = new Page<>(pageNum, pageSize);
        LocalDateTime startDateTime = null;
        LocalDateTime endDateTime = null;
        LocalDateTime submitDateTime = null;
        if (StringUtils.isNotBlank(submitDate)) {
            DateTimeFormatter submitDateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            try {
                submitDateTime = LocalDateTime.parse(submitDate, submitDateFormatter);
            } catch (Exception e) {
                throw new BusinessException("滑动时间传参格式不正确，请重试" + e);
            }
        }
        Integer tenantId = SecurityUtils.getTenantId();
        Long nowUserId = SecurityUtils.getUserId();
        LocalDate start = null;
        LocalDate end = null;
        List<Integer> reportIds = new ArrayList<>();
        CommonPage<PmWorkReport> returnPage = new CommonPage<>(reportList, reportPage.getTotal(), pageSize, pageNum);

        Set<Integer> reportIdsByUser = new HashSet<>();
        Set<Integer> reportIdsByDate = new HashSet<>();
        Set<Integer> reportIdsByProject = new HashSet<>();
        Set<Integer> reportIdsSet = new HashSet<>();

        LambdaQueryWrapper<PmWorkReport> reportQuery = Wrappers.lambdaQuery();

        if (StringUtils.isNotBlank(startDate) && StringUtils.isNotBlank(endDate)) {
            DateTimeFormatter formatter = null;
            try {
                formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            } catch (Exception e) {
                throw new BusinessException("时间传参格式不正确请重试");
            }
            start = LocalDate.parse(startDate, formatter);
            end = LocalDate.parse(endDate, formatter);
            startDateTime = start.atStartOfDay();
            endDateTime = end.atTime(23, 59, 59);
            reportQuery.select(PmWorkReport::getId).eq(PmWorkReport::getReportStatus, 1).between(PmWorkReport::getSubmitDate, startDateTime, endDateTime);
            reportIdsByDate = pmWorkReportMapper.selectList(reportQuery).stream().map(PmWorkReport::getId).collect(Collectors.toSet());
        }

        if (projectId != null) {
            LambdaQueryWrapper<PmWorkContent> contentLambdaQuery = Wrappers.lambdaQuery();
            contentLambdaQuery.select(PmWorkContent::getReportId).eq(PmWorkContent::getProjectId, projectId);
            reportIdsByProject = pmWorkContentMapper.selectList(contentLambdaQuery).stream().map(PmWorkContent::getReportId).collect(Collectors.toSet());
        }

        if (userId != null) {
            reportQuery.eq(PmWorkReport::getSubmitterId, userId)
                    .and(wrappers -> wrappers.apply("FIND_IN_SET(" + nowUserId + ", cc_to) > 0"));
            reportIdsByUser = pmWorkReportMapper.selectList(reportQuery).stream().map(PmWorkReport::getId).collect(Collectors.toSet());
            if (reportIdsByProject.isEmpty() && reportIdsByUser.isEmpty()) {
                return returnPage;
            }
        }

        if (!reportIdsByUser.isEmpty() && !reportIdsByProject.isEmpty() && !reportIdsByDate.isEmpty()) {
            reportIdsSet.addAll(reportIdsByUser);
            reportIdsSet.retainAll(reportIdsByProject);
            reportIdsSet.retainAll(reportIdsByDate);
            if (reportIdsSet.isEmpty()) {
                return returnPage;
            }
        } else if (!reportIdsByUser.isEmpty() && !reportIdsByProject.isEmpty()) {
            reportIdsSet.addAll(reportIdsByUser);
            reportIdsSet.retainAll(reportIdsByProject);
            if (reportIdsSet.isEmpty()) {
                return returnPage;
            }
        } else if (!reportIdsByUser.isEmpty() && !reportIdsByDate.isEmpty()) {
            reportIdsSet.addAll(reportIdsByUser);
            reportIdsSet.retainAll(reportIdsByDate);
            if (reportIdsSet.isEmpty()) {
                return returnPage;
            }
        } else if (!reportIdsByProject.isEmpty() && !reportIdsByDate.isEmpty()) {
            reportIdsSet.addAll(reportIdsByProject);
            reportIdsSet.retainAll(reportIdsByDate);
            if (reportIdsSet.isEmpty()) {
                return returnPage;
            }
        } else if (!reportIdsByUser.isEmpty()) {
            reportIdsSet.addAll(reportIdsByUser);
        } else if (!reportIdsByProject.isEmpty()) {
            reportIdsSet.addAll(reportIdsByProject);
        } else if (!reportIdsByDate.isEmpty()) {
            reportIdsSet.addAll(reportIdsByDate);
        }

        reportIds = new ArrayList<>(reportIdsSet);

        if (projectAscription == 1) {
            LambdaQueryWrapper<PmWorkReport> headerQuery = Wrappers.lambdaQuery();
            headerQuery.in(!reportIds.isEmpty(), PmWorkReport::getId, reportIds)
                    .and(wrappers -> wrappers.apply("FIND_IN_SET(" + nowUserId + ", cc_to) > 0"));
            reportIds = pmWorkReportMapper.selectList(headerQuery).stream().map(PmWorkReport::getId).collect(Collectors.toList());
        }

        List<PmWorkContent> pmWorkContentList = new ArrayList<>();
        Long userId2 = SecurityUtils.getUserId();
        List<Long> userIds = new ArrayList<>();
        List<Integer> receiveList = receive();
        if (receiveList.isEmpty() && projectAscription == 2) {
            return returnPage;
        }

        LambdaQueryWrapper<PmWorkContent> contentLambdaQuery = Wrappers.lambdaQuery();
        if (reportId != null && reportId > 0) {
            contentLambdaQuery.eq(PmWorkContent::getReportId, reportId);
            pmWorkContentList = pmWorkContentMapper.selectList(contentLambdaQuery);
            if (pmWorkContentList.isEmpty()) {
                throw new BusinessException("该报告已被删除!");
            }
        } else {
            switch (projectAscription) {
                case 1:
                    List<Integer> headProjects = head();
                    if (headProjects.isEmpty()) {
                        return returnPage;
                    }
                    contentLambdaQuery.in(PmWorkContent::getProjectId, headProjects);
                    break;
                case 2:
                    contentLambdaQuery.in(PmWorkContent::getReportId, receiveList);
                    break;
                case 3:
                    List<Integer> sentOutList = sentOut();
                    if (sentOutList.isEmpty()) {
                        return returnPage;
                    }
                    contentLambdaQuery.in(PmWorkContent::getReportId, sentOutList);
                    break;
                default:
                    throw new BusinessException("查询标识有误!");
            }
            if (!reportIds.isEmpty()) {
                contentLambdaQuery.in(PmWorkContent::getReportId, reportIds);
            }
            pmWorkContentList = pmWorkContentMapper.selectList(contentLambdaQuery);
            if (pmWorkContentList.isEmpty()) {
                return returnPage;
            }
        }

        List<Integer> reportIds2 = pmWorkContentList.stream().distinct().map(PmWorkContent::getReportId).collect(Collectors.toList());

        LambdaQueryWrapper<PmWorkReport> reportQuery1 = Wrappers.lambdaQuery();
        reportQuery1.eq(PmWorkReport::getTenantId, tenantId).eq(PmWorkReport::getReportStatus, 1);
        if (reportId != null && reportId != 0) {
            reportQuery1.eq(PmWorkReport::getId, reportId);
        } else {
            reportQuery1.in(PmWorkReport::getId, reportIds2);
            // 判断上下滑动以及数量
            if (upOrDown != null && slideSum != null && submitDateTime != null) {
                if (slideSum > 0) {
                    // 向下滑动
                    if (upOrDown == 0) {
                        reportQuery1.lt(PmWorkReport::getSubmitDate, submitDateTime).orderByDesc(PmWorkReport::getSubmitDate);
                    }
                    // 向上滑动
                    else if (upOrDown == 1) {
                        reportQuery1.gt(PmWorkReport::getSubmitDate, submitDateTime).orderByAsc(PmWorkReport::getSubmitDate);
                    } else {
                        throw new BusinessException("上下滑动参数异常");
                    }
                    // 设置pageSize为slideSum，确保返回的数据量为slideSum
                    pageNum = 1;
                    pageSize = slideSum;
                } else {
                    throw new BusinessException("滑动数量参数必须是大于0正整数");
                }
            } else {
                reportQuery1.orderByDesc(PmWorkReport::getSubmitDate);
            }
        }

        reportPage = pmWorkReportMapper.selectPage(new Page<>(pageNum, pageSize), reportQuery1);
        reportList = reportPage.getRecords();

        // 查询已读状态
        LambdaQueryWrapper<PmReceive> statusQuery = Wrappers.lambdaQuery();
        statusQuery.select(PmReceive::getReportId, PmReceive::getReadFlag).eq(PmReceive::getReceiverId, userId2);
        if (reportId != null && reportId != 0) {
            statusQuery.eq(PmReceive::getReportId, reportId);
        } else if (!receiveList.isEmpty()) {
            statusQuery.in(PmReceive::getReportId, receiveList);
        }
        List<PmReceive> receiveList2 = pmReceiveMapper.selectList(statusQuery);

        Map<Integer, Integer> reportReadFlags = new HashMap<>();
        for (PmReceive pmReceive : receiveList2) {
            Integer reportId2 = pmReceive.getReportId();
            reportReadFlags.put(reportId2, pmReceive.getReadFlag());
        }

        for (PmWorkReport report : reportList) {
            List<PmWorkContent> contents = pmWorkContentList.stream().filter(content -> content.getReportId().equals(report.getId())).collect(Collectors.toList());
            report.setWorkContents(contents);
            userIds.add(report.getSubmitterId());

            Integer readFlagValue = reportReadFlags.get(report.getId());
            report.setReadFlag(readFlagValue);

            // 创建人名字替换
            if (!userIds.isEmpty()) {
                List<SysUser> nickNames = nickNames(userIds);
                Map<Long, String> userNicknameMap = nickNames.stream().collect(Collectors.toMap(SysUser::getUserId, SysUser::getNickName));
                report.setCreateBy(userNicknameMap.get(report.getSubmitterId()));
            }
        }

        // 已读未读数量查询
        List<PmReceive> receives = new ArrayList<>();
        if (!receiveList.isEmpty()) {
            receives = receives(reportIds2);
        }

        Map<Integer, List<PmReceive>> reportReceivesMap = new HashMap<>();
        if (!receives.isEmpty()) {
            reportReceivesMap = receives.stream().collect(Collectors.groupingBy(PmReceive::getReportId));
        }

        Set<Long> userIdSet = new HashSet<>();
        for (PmWorkReport report : reportList) {
            Long submitterId = report.getSubmitterId();
            userIdSet.add(submitterId);
        }
        List<Long> userIdList = new ArrayList<>(userIdSet);

        List<SysUser> sysUsers = nickNames(userIdList);

        if (sysUsers != null) {
            for (PmWorkReport report : reportList) {
                List<Long> readAlready = new ArrayList<>();
                List<Long> readNotAlready = new ArrayList<>();
                int readCount = 0;
                int unreadCount = 0;
                if (!reportReceivesMap.isEmpty()) {
                    List<PmReceive> reportReceives = reportReceivesMap.getOrDefault(report.getId(), Collections.emptyList());
                    for (PmReceive pmReceive : reportReceives) {
                        if (pmReceive.getReadFlag() == 1) {
                            readCount++;
                            readAlready.add(pmReceive.getReceiverId());
                        } else {
                            unreadCount++;
                            readNotAlready.add(pmReceive.getReceiverId());
                        }
                    }
                }

                PmReportReadersVO readUnreadVO = new PmReportReadersVO(readAlready, readNotAlready, readCount, unreadCount);
                report.setPmReportReaders(readUnreadVO);

                // 头像
                for (SysUser sysUser : sysUsers) {
                    if (sysUser.getUserId().equals(report.getSubmitterId())) {
                        report.setAvatar(sysUser.getAvatar());
                        break;
                    }
                }
            }
        }

        return new CommonPage<PmWorkReport>(reportList, reportPage.getTotal(), pageSize, pageNum);
    }

    /**
     * @description: 日报上下滑动
     * @author: fu
     * @date: 2024/8/8 19:22
     * @param: [upOrDown, slideSum, submitDate]
     * @return: java.util.List<com.usky.iot.vo.PmWorkReportSlideVO>
     **/
    @Override
    public PmWorkReportSlideVO slide(Integer upOrDown, Integer slideSum, LocalDateTime submitDate) {
        PmWorkReportSlideVO reportSlide = new PmWorkReportSlideVO();
        if (slideSum <= 0) {
            throw new BusinessException("slideSum 必须为正整数！");
        }
        if (submitDate == null) {
            return reportSlide;
        }

        List<PmWorkReport> reportUp = new ArrayList<>();
        List<PmWorkReport> reportDown = new ArrayList<>();
        LambdaQueryWrapper<PmWorkReport> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.last("LIMIT " + slideSum);
        if (upOrDown == 1) {
            queryWrapper.gt(PmWorkReport::getSubmitDate, submitDate)
                    .orderByAsc(PmWorkReport::getSubmitDate);
            reportUp = pmWorkReportMapper.selectList(queryWrapper);
            if (reportUp.isEmpty()) {
                throw new BusinessException("已经是第一篇报告了！");
            }
            reportSlide.setSlideUp(reportUp);
        } else if (upOrDown == 2) {
            queryWrapper.lt(PmWorkReport::getSubmitDate, submitDate)
                    .orderByDesc(PmWorkReport::getSubmitDate);
            reportDown = pmWorkReportMapper.selectList(queryWrapper);
            if (reportDown.isEmpty()) {
                throw new BusinessException("已经是最后一篇报告了！");
            }
            reportSlide.setSlideDown(reportDown);
        } else {
            throw new BusinessException("upOrDown 参数无效！");
        }

        return reportSlide;
    }


    /**
     * @description: 获取报告接收人-工具
     * @author: fu
     * @date: 2024/8/8 19:22
     * @param: [report]
     * @return: java.util.List<com.usky.iot.domain.PmReceive>
     **/
    private List<PmReceive> receives(List<Integer> reports) {
        LambdaQueryWrapper<PmReceive> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.select(PmReceive::getReportId, PmReceive::getReadFlag, PmReceive::getReceiverId).in(PmReceive::getReportId, reports);
        return pmReceiveMapper.selectList(queryWrapper);
    }

    /**
     * @description: 获取时间段内报告列表（按报告时间查询）-工具
     * @author: fu
     * @date: 2024/8/8 19:22
     * @param: [startDate, endDate]
     * @return: java.util.List<java.lang.Integer>
     **/
    private List<Integer> reports(LocalDate startDate, LocalDate endDate) {
        LambdaQueryWrapper<PmWorkReport> reportsQuery = Wrappers.lambdaQuery();
        reportsQuery.select(PmWorkReport::getId).between(PmWorkReport::getReportDate, startDate, endDate);
        List<PmWorkReport> pmWorkReportList = pmWorkReportMapper.selectList(reportsQuery);
        return pmWorkReportList.stream().map(PmWorkReport::getId).collect(Collectors.toList());
    }

    /**
     * @description: 项目查询-工具
     * @author: fu
     * @date: 2024/8/8 19:22
     * @return: java.util.List<java.lang.Integer>
     **/
    private List<PmProject> projects(Integer projectId) {
        Long userId = SecurityUtils.getUserId();
        LambdaQueryWrapper<PmProject> projectsQuery = Wrappers.lambdaQuery();
        projectsQuery.select(PmProject::getId, PmProject::getProjectName);
        if (projectId != null && projectId >= 0) {
            projectsQuery.eq(PmProject::getId, projectId);
            return pmProjectMapper.selectList(projectsQuery);
        } else {
            projectsQuery.and(qw -> qw
                    .or().apply(Objects.nonNull(DataScopeContextHolder.getDataScopeSql()), DataScopeContextHolder.getDataScopeSql())
                    .or().eq(PmProject::getProjectHead, userId)
                    .or().eq(PmProject::getCreateBy, SecurityUtils.getUsername())
                    .or().apply("FIND_IN_SET('" + SecurityUtils.getUserId() + "', project_member) > 0")
            );
            // projectsQuery.apply(Objects.nonNull(DataScopeContextHolder.getDataScopeSql()), DataScopeContextHolder.getDataScopeSql());
        }
        projectsQuery.eq(PmProject::getDelFlag, 0);
        return pmProjectMapper.selectList(projectsQuery);
    }

    /**
     * @description: 获取用户列表-工具
     * @author: fu
     * @date: 2024/8/8 19:22
     * @param: [userId]
     * @return: java.util.List<com.usky.iot.domain.SysUser>
     **/
    private List<SysUser> userNameList(List<Long> userId, Integer workerOrProject) {
        LambdaQueryWrapper<SysUser> userNameQuery = Wrappers.lambdaQuery();
        userNameQuery.select(SysUser::getUserId, SysUser::getNickName, SysUser::getUserName, SysUser::getPhonenumber, SysUser::getAvatar,
                SysUser::getSex, SysUser::getDeptId, SysUser::getAddress);
        if (!userId.isEmpty()) {
            userNameQuery.eq(SysUser::getDelFlag, 0).eq(SysUser::getStatus, 0).in(SysUser::getUserId, userId);
            return sysUserMapper.selectList(userNameQuery);
        } else {
            userNameQuery.eq(SysUser::getUserId, SecurityUtils.getUserId());
        }
        return sysUserMapper.selectList(userNameQuery);
    }

    /**
     * @description: 工时统计-工具
     * @author: fu
     * @date: 2024/8/8 19:22
     * @param: [startDate, endDate, projectName, projectAscription]
     * @return: java.util.List<com.usky.iot.domain.PmWorkReport>
     **/
    private List<PmWorkContent> workTimeCount(List<Long> users, List<Integer> project, String startDate, String endDate) {
        List<PmWorkContent> pmWorkContentList = new ArrayList<>();
        Integer tenantId = SecurityUtils.getTenantId();
        Long deptId = SecurityUtils.getLoginUser().getSysUser().getDeptId();
        LambdaQueryWrapper<PmWorkContent> workTimeQuery = Wrappers.lambdaQuery();
        workTimeQuery.select(PmWorkContent::getSubmitterId, PmWorkContent::getReportId, PmWorkContent::getProjectId, PmWorkContent::getProjectName,
                        PmWorkContent::getWorkTime, PmWorkContent::getDeptId, PmWorkContent::getTenantId)
                .eq(PmWorkContent::getTenantId, tenantId);
        if (!users.isEmpty()) {
            workTimeQuery.in(PmWorkContent::getSubmitterId, users);
        }
        if (!project.isEmpty()) {
            workTimeQuery.in(PmWorkContent::getProjectId, project);
        }
        if (StringUtils.isNotBlank(startDate) && StringUtils.isNotBlank(endDate)) {
            LocalDate start = LocalDate.parse(startDate);
            LocalDate end = LocalDate.parse(endDate);
            List<Integer> reports = reports(start, end);
            if (!reports.isEmpty()) {
                workTimeQuery.in(PmWorkContent::getReportId, reports);
            } else {
                return pmWorkContentList;
            }
        }
        pmWorkContentList = pmWorkContentMapper.selectList(workTimeQuery);

        Map<String, PmWorkContent> workTimeMap = new HashMap<>();
        for (PmWorkContent content : pmWorkContentList) {
            String key = content.getSubmitterId() + "_" + content.getProjectId();
            PmWorkContent existingContent = workTimeMap.get(key);
            if (existingContent == null) {
                workTimeMap.put(key, content);
            } else {
                existingContent.setWorkTime(existingContent.getWorkTime().add(content.getWorkTime()));
            }
        }

        return new ArrayList<>(workTimeMap.values());
    }

    /**
     * @description: 工时统计
     * @author: fu
     * @date: 2024/8/8 19:22
     * @param: [userId, projectId, startDate, endDate]
     *      * @param userId          用户id
     *      * @param filter          是否过滤0工时（默认1：不过滤；2：过滤）
     *      * @param startDate       开始时间
     *      * @param endDate         结束时间
     *      * @param workerOrProject 打工仔还是项目（默认1：打工仔；2：项目）
     * @return: java.util.List<com.usky.iot.domain.WorkTimeExportVO>
     **/
    @DataScope
    @Override
    public List<Object> workHourStatisticNew(PmWorkHourStatisticRequestVO requestVO) {
        List<Long> userId = new ArrayList<>();
        if (requestVO.getUserIds() != null) {
            userId = requestVO.getUserIds();
        }
        Integer projectId = requestVO.getProjectId();
        int filter = 1;
        if (requestVO.getFilter() != null) {
            filter = requestVO.getFilter();
        }
        String startDate = requestVO.getStartDate();
        String endDate = requestVO.getEndDate();
        int workerOrProject = 1;
        if (requestVO.getWorkerOrProject() != null) {
            workerOrProject = requestVO.getWorkerOrProject();
        }
        if (StringUtils.isBlank(startDate) || StringUtils.isBlank(endDate)) {
            startDate = LocalDate.now().with(TemporalAdjusters.firstDayOfYear()).toString();
            endDate = LocalDate.now().with(TemporalAdjusters.lastDayOfYear()).toString();
        }

        List<ProjectWorkTimeVO> projectWorkTime = new ArrayList<>();
        List<UserWorkTimeVO> userWorkTimeVO = new ArrayList<>();
        List<Object> returnList = new ArrayList<>();

        if (StringUtils.isBlank(startDate) || StringUtils.isBlank(endDate)) {
            throw new BusinessException("请设置查询时间范围！");
        }

        List<SysUser> users = userNameList(userId, workerOrProject);
        List<Long> userIds = new ArrayList<>();
        List<String> nickName = new ArrayList<>();
        for (SysUser user : users) {
            userIds.add(user.getUserId());
            nickName.add(user.getNickName());
        }

        List<PmProject> pmProjects = projects(projectId);
        List<String> pmProjectName = new ArrayList<>();
        List<Integer> pmProjectId = new ArrayList<>();
        for (PmProject project : pmProjects) {
            pmProjectName.add(project.getProjectName());
            pmProjectId.add(project.getId());
        }

        // 统计userId每个项目所需工时
        List<WorkHoursStatisticsVO> userAndProject = new ArrayList<>();
        List<PmWorkContent> pmWorkContentList = workTimeCount(userIds, pmProjectId, startDate, endDate);
        if (!pmWorkContentList.isEmpty()) {
            for (PmWorkContent content : pmWorkContentList) {
                WorkHoursStatisticsVO workHoursStatisticsVO = new WorkHoursStatisticsVO();
                Long submitterId = content.getSubmitterId();
                Integer projectId1 = content.getProjectId();
                BigDecimal workTime = content.getWorkTime();
                workHoursStatisticsVO.setWorkTime(workTime);
                for (SysUser user : users) {
                    Long userId1 = user.getUserId();
                    String nickName1 = user.getNickName();
                    if (userId1.equals(submitterId)) {
                        workHoursStatisticsVO.setNickName(nickName1);
                    }
                }
                for (PmProject project : pmProjects) {
                    Integer projectId2 = project.getId();
                    String projectName = project.getProjectName();
                    if (Objects.equals(projectId2, projectId1)) {
                        workHoursStatisticsVO.setProjectName(projectName);
                    }
                }
                userAndProject.add(workHoursStatisticsVO);
            }
        }
        List<WorkHoursStatisticsVO> userAndProjectD = userAndProject;

        // 判断是否为项目维度
        if (workerOrProject != 1) {
            returnList.add(nickName);
            // 重组返回数据结构
            for (String name : pmProjectName) {
                ProjectWorkTimeVO projectWorkTimeVO = new ProjectWorkTimeVO();
                projectWorkTimeVO.setProjectOrPerson(name);
                List<BigDecimal> workTime = new ArrayList<>();
                boolean hasNonZeroWorkTime = false;
                if (userAndProject.isEmpty()) {
                    for (String currentNickName : nickName) {
                        workTime.add(BigDecimal.ZERO);
                    }
                } else {
                    for (String currentNickName : nickName) {
                        boolean foundWorkTime = false;
                        for (WorkHoursStatisticsVO workHoursStatisticsVO : userAndProject) {
                            String userNickName = workHoursStatisticsVO.getNickName();
                            String projectName = workHoursStatisticsVO.getProjectName();
                            BigDecimal userProjectWorkTime = workHoursStatisticsVO.getWorkTime();
                            if (projectName == name && userNickName == currentNickName) {
                                workTime.add(userProjectWorkTime);
                                if (userProjectWorkTime.compareTo(BigDecimal.ZERO) != 0) {
                                    hasNonZeroWorkTime = true;
                                }
                                foundWorkTime = true;
                                break;
                            }
                        }
                        if (!foundWorkTime) {
                            workTime.add(BigDecimal.ZERO);
                        }
                    }
                }
                // 过滤0工时
                if (filter != 2 || hasNonZeroWorkTime) {
                    projectWorkTimeVO.setWorkTime(workTime);
                    projectWorkTime.add(projectWorkTimeVO);
                }
            }
            returnList.add(projectWorkTime);


            // 先过滤掉总工时为0的项目
            Set<Integer> nonZeroProjectIndices = new HashSet<>();
            for (int i = 0; i < pmProjectName.size(); i++) {
                BigDecimal totalWorkTime = BigDecimal.ZERO;
                for (WorkHoursStatisticsVO workHoursStatisticsVO : userAndProjectD) {
                    if (workHoursStatisticsVO.getProjectName().equals(pmProjectName.get(i))) {
                        totalWorkTime = totalWorkTime.add(workHoursStatisticsVO.getWorkTime());
                    }
                }
                if (totalWorkTime.compareTo(BigDecimal.ZERO) != 0) {
                    nonZeroProjectIndices.add(i);
                }
            }

            // 重组返回数据结构
            for (String uName : nickName) {
                String name1 = uName;
                UserWorkTimeVO userWorkTimeVO2 = new UserWorkTimeVO();
                userWorkTimeVO2.setProjectOrPerson(name1);
                List<BigDecimal> workTime1 = new ArrayList<>();

                for (int i = 0; i < pmProjectName.size(); i++) {
                    BigDecimal userProjectWorkTime = BigDecimal.ZERO;
                    boolean foundWorkTime = false;
                    for (WorkHoursStatisticsVO workHoursStatisticsVO : userAndProjectD) {
                        String userNickName = workHoursStatisticsVO.getNickName();
                        String projectName = workHoursStatisticsVO.getProjectName();
                        if (userNickName.equals(name1) && projectName.equals(pmProjectName.get(i))) {
                            userProjectWorkTime = workHoursStatisticsVO.getWorkTime();
                            foundWorkTime = true;
                            break;
                        }
                    }
                    if (foundWorkTime && nonZeroProjectIndices.contains(i)) {
                        workTime1.add(userProjectWorkTime);
                    } else {
                        workTime1.add(BigDecimal.ZERO);
                    }
                }

                // 过滤0工时
                boolean hasNonZeroWorkTime1 = false;
                for (BigDecimal time : workTime1) {
                    if (time.compareTo(BigDecimal.ZERO) != 0) {
                        hasNonZeroWorkTime1 = true;
                        break;
                    }
                }

                if (filter != 2 || hasNonZeroWorkTime1) {
                    userWorkTimeVO2.setWorkTime(workTime1);
                    userWorkTimeVO.add(userWorkTimeVO2);
                }
            }

            if (filter == 2) {
                for (int i = pmProjectName.size() - 1; i >= 0; i--) {
                    if (!nonZeroProjectIndices.contains(i)) {
                        pmProjectName.remove(i);
                    }
                }
                for (int i = userWorkTimeVO.size() - 1; i >= 0; i--) {
                    List<BigDecimal> workTime = userWorkTimeVO.get(i).getWorkTime();
                    for (int j = workTime.size() - 1; j >= 0; j--) {
                        if (!nonZeroProjectIndices.contains(j)) {
                            workTime.remove(j);
                        }
                    }
                    if (workTime.isEmpty()) {
                        userWorkTimeVO.remove(i);
                    }
                }
            }

            returnList.add(pmProjectName);
            returnList.add(userWorkTimeVO);

        } else {
            returnList.add(pmProjectName);
            // 重组返回数据结构
            for (String uName : nickName) {
                String name = uName;
                UserWorkTimeVO userWorkTimeVO2 = new UserWorkTimeVO();
                userWorkTimeVO2.setProjectOrPerson(name);
                List<BigDecimal> workTime = new ArrayList<>();
                boolean hasNonZeroWorkTime = false;
                if (userAndProjectD.isEmpty()) {
                    for (String currentNickName : pmProjectName) {
                        workTime.add(BigDecimal.ZERO);
                    }
                } else {
                    for (String currentNickName : pmProjectName) {
                        boolean foundWorkTime = false;
                        for (WorkHoursStatisticsVO workHoursStatisticsVO : userAndProjectD) {
                            String userNickName = workHoursStatisticsVO.getNickName();
                            String projectName = workHoursStatisticsVO.getProjectName();
                            BigDecimal userProjectWorkTime = workHoursStatisticsVO.getWorkTime();
                            if (Objects.equals(userNickName, name) && Objects.equals(projectName, currentNickName)) {
                                workTime.add(userProjectWorkTime);
                                if (userProjectWorkTime.compareTo(BigDecimal.ZERO) != 0) {
                                    hasNonZeroWorkTime = true;
                                }
                                foundWorkTime = true;
                                break;
                            }
                        }
                        if (!foundWorkTime) {
                            workTime.add(BigDecimal.ZERO);
                        }
                    }
                }
                // 过滤0工时
                if (filter != 2 || hasNonZeroWorkTime) {
                    userWorkTimeVO2.setWorkTime(workTime);
                    userWorkTimeVO.add(userWorkTimeVO2);
                }
            }
            returnList.add(userWorkTimeVO);


            List<String> filteredNickName = new ArrayList<>();
            List<ProjectWorkTimeVO> filteredProjectWorkTime = new ArrayList<>();

            for (String name : pmProjectName) {
                ProjectWorkTimeVO projectWorkTimeVO = new ProjectWorkTimeVO();
                projectWorkTimeVO.setProjectOrPerson(name);
                List<BigDecimal> workTime = new ArrayList<>();
                boolean hasNonZeroWorkTime = false;

                if (userAndProject.isEmpty()) {
                    for (String currentNickName : nickName) {
                        workTime.add(BigDecimal.ZERO);
                    }
                } else {
                    for (String currentNickName : nickName) {
                        boolean foundWorkTime = false;
                        for (WorkHoursStatisticsVO workHoursStatisticsVO : userAndProject) {
                            String userNickName = workHoursStatisticsVO.getNickName();
                            String projectName = workHoursStatisticsVO.getProjectName();
                            BigDecimal userProjectWorkTime = workHoursStatisticsVO.getWorkTime();
                            if (projectName.equals(name) && userNickName.equals(currentNickName)) {
                                workTime.add(userProjectWorkTime);
                                if (userProjectWorkTime.compareTo(BigDecimal.ZERO) != 0) {
                                    hasNonZeroWorkTime = true;
                                }
                                foundWorkTime = true;
                                break;
                            }
                        }
                        if (!foundWorkTime) {
                            workTime.add(BigDecimal.ZERO);
                        }
                    }
                }

                // 过滤0工时
                if (filter != 2 || hasNonZeroWorkTime) {
                    projectWorkTimeVO.setWorkTime(workTime);
                    filteredProjectWorkTime.add(projectWorkTimeVO);
                }
            }

            // 过滤 nickName 和 projectWorkTime
            if (filter == 2) {
                Set<Integer> nonZeroIndices = new HashSet<>();
                for (int i = 0; i < nickName.size(); i++) {
                    BigDecimal totalWorkTime = BigDecimal.ZERO;
                    for (int j = 0; j < filteredProjectWorkTime.size(); j++) {
                        totalWorkTime = totalWorkTime.add(filteredProjectWorkTime.get(j).getWorkTime().get(i));
                    }
                    if (totalWorkTime.compareTo(BigDecimal.ZERO) != 0) {
                        filteredNickName.add(nickName.get(i));
                        nonZeroIndices.add(i);
                    }
                }
                for (int i = filteredProjectWorkTime.size() - 1; i >= 0; i--) {
                    List<BigDecimal> workTime = filteredProjectWorkTime.get(i).getWorkTime();
                    for (int j = workTime.size() - 1; j >= 0; j--) {
                        if (!nonZeroIndices.contains(j)) {
                            workTime.remove(j);
                        }
                    }
                    if (workTime.isEmpty()) {
                        filteredProjectWorkTime.remove(i);
                    }
                }
            } else {
                filteredNickName.addAll(nickName);
            }

            returnList.add(filteredNickName);
            returnList.add(filteredProjectWorkTime);
        }
        return returnList;
    }

    // 回退代码
    @DataScope
    @Override
    public List<Object> workHourStatistic(Long userId, Integer projectId, Integer filter, String startDate, String endDate, Integer workerOrProject) {
        List<ProjectWorkTimeVO> projectWorkTime = new ArrayList<>();
        List<UserWorkTimeVO> userWorkTimeVO = new ArrayList<>();
        List<ProjectWorkTimeVO> projectWorkTime1 = new ArrayList<>();
        List<UserWorkTimeVO> userWorkTimeVO1 = new ArrayList<>();
        List<Object> returnList = new ArrayList<>();
        if (StringUtils.isBlank(startDate) || StringUtils.isBlank(endDate)) {
            throw new BusinessException("请设置查询时间范围！");
        }

        List<PmProject> pmProjects = projects(projectId);
        List<String> pmProjectName = new ArrayList<>();
        List<Integer> pmProjectId = new ArrayList<>();
        for (PmProject project : pmProjects) {
            pmProjectName.add(project.getProjectName());
            pmProjectId.add(project.getId());
        }

        List<Long> userIdS = new ArrayList<>();
        if (userId != null) {
            userIdS.add(userId);
        }
        List<SysUser> users = userNameList(userIdS, workerOrProject);
        List<Long> userIds = new ArrayList<>();
        List<String> nickName = new ArrayList<>();
        for (SysUser user : users) {
            userIds.add(user.getUserId());
            nickName.add(user.getNickName());
        }

        // 统计userId每个项目所需工时
        List<WorkHoursStatisticsVO> userAndProject = new ArrayList<>();
        List<PmWorkContent> pmWorkContentList = workTimeCount(userIds, pmProjectId, startDate, endDate);
        if (!pmWorkContentList.isEmpty()) {
            for (PmWorkContent content : pmWorkContentList) {
                WorkHoursStatisticsVO workHoursStatisticsVO = new WorkHoursStatisticsVO();
                Long submitterId = content.getSubmitterId();
                Integer projectId1 = content.getProjectId();
                BigDecimal workTime = content.getWorkTime();
                workHoursStatisticsVO.setWorkTime(workTime);
                for (SysUser user : users) {
                    Long userId1 = user.getUserId();
                    String nickName1 = user.getNickName();
                    if (userId1.equals(submitterId)) {
                        workHoursStatisticsVO.setNickName(nickName1);
                    }
                }
                for (PmProject project : pmProjects) {
                    Integer projectId2 = project.getId();
                    String projectName = project.getProjectName();
                    if (projectId2.equals(projectId1)) {
                        workHoursStatisticsVO.setProjectName(projectName);
                    }
                }
                userAndProject.add(workHoursStatisticsVO);
            }
        }
        List<WorkHoursStatisticsVO> userAndProjectD = userAndProject;

        if (workerOrProject != 1) {
            returnList.add(nickName);
            // 重组返回数据结构
            for (String name : pmProjectName) {
                ProjectWorkTimeVO projectWorkTimeVO = new ProjectWorkTimeVO();
                projectWorkTimeVO.setProjectOrPerson(name);
                List<BigDecimal> workTime = new ArrayList<>();
                boolean hasNonZeroWorkTime = false;
                if (userAndProject.isEmpty()) {
                    for (String currentNickName : nickName) {
                        workTime.add(BigDecimal.ZERO);
                    }
                } else {
                    for (String currentNickName : nickName) {
                        boolean foundWorkTime = false;
                        for (WorkHoursStatisticsVO workHoursStatisticsVO : userAndProject) {
                            String userNickName = workHoursStatisticsVO.getNickName();
                            String projectName = workHoursStatisticsVO.getProjectName();
                            BigDecimal userProjectWorkTime = workHoursStatisticsVO.getWorkTime();
                            if (projectName == name && userNickName == currentNickName) {
                                workTime.add(userProjectWorkTime);
                                if (userProjectWorkTime.compareTo(BigDecimal.ZERO) != 0) {
                                    hasNonZeroWorkTime = true;
                                }
                                foundWorkTime = true;
                                break;
                            }
                        }
                        if (!foundWorkTime) {
                            workTime.add(BigDecimal.ZERO);
                        }
                    }
                }
                // 过滤0工时
                if (filter != 2 || hasNonZeroWorkTime) {
                    projectWorkTimeVO.setWorkTime(workTime);
                    projectWorkTime.add(projectWorkTimeVO);
                }
            }
            returnList.add(projectWorkTime);


            returnList.add(pmProjectName);
            // 重组返回数据结构
            for (String uName : nickName) {
                String name1 = uName;
                UserWorkTimeVO userWorkTimeVO2 = new UserWorkTimeVO();
                userWorkTimeVO2.setProjectOrPerson(name1);
                List<BigDecimal> workTime1 = new ArrayList<>();
                boolean hasNonZeroWorkTime1 = false;
                if (userAndProjectD.isEmpty()) {
                    for (String currentNickName : pmProjectName) {
                        workTime1.add(BigDecimal.ZERO);
                    }
                } else {
                    for (String currentNickName : pmProjectName) {
                        boolean foundWorkTime = false;
                        for (WorkHoursStatisticsVO workHoursStatisticsVO : userAndProjectD) {
                            String userNickName = workHoursStatisticsVO.getNickName();
                            String projectName = workHoursStatisticsVO.getProjectName();
                            BigDecimal userProjectWorkTime = workHoursStatisticsVO.getWorkTime();
                            if (userNickName == name1 && projectName == currentNickName) {
                                workTime1.add(userProjectWorkTime);
                                if (userProjectWorkTime.compareTo(BigDecimal.ZERO) != 0) {
                                    hasNonZeroWorkTime1 = true;
                                }
                                foundWorkTime = true;
                                break;
                            }
                        }
                        if (!foundWorkTime) {
                            workTime1.add(BigDecimal.ZERO);
                        }
                    }
                }
                // 过滤0工时
                if (filter != 2 || hasNonZeroWorkTime1) {
                    userWorkTimeVO2.setWorkTime(workTime1);
                    userWorkTimeVO.add(userWorkTimeVO2);
                }
            }
            returnList.add(userWorkTimeVO);

        } else {
            returnList.add(pmProjectName);
            // 重组返回数据结构
            for (String uName : nickName) {
                String name = uName;
                UserWorkTimeVO userWorkTimeVO2 = new UserWorkTimeVO();
                userWorkTimeVO2.setProjectOrPerson(name);
                List<BigDecimal> workTime = new ArrayList<>();
                boolean hasNonZeroWorkTime = false;
                if (userAndProjectD.isEmpty()) {
                    for (String currentNickName : pmProjectName) {
                        workTime.add(BigDecimal.ZERO);
                    }
                } else {
                    for (String currentNickName : pmProjectName) {
                        boolean foundWorkTime = false;
                        for (WorkHoursStatisticsVO workHoursStatisticsVO : userAndProjectD) {
                            String userNickName = workHoursStatisticsVO.getNickName();
                            String projectName = workHoursStatisticsVO.getProjectName();
                            BigDecimal userProjectWorkTime = workHoursStatisticsVO.getWorkTime();
                            if (userNickName == name && projectName == currentNickName) {
                                workTime.add(userProjectWorkTime);
                                if (userProjectWorkTime.compareTo(BigDecimal.ZERO) != 0) {
                                    hasNonZeroWorkTime = true;
                                }
                                foundWorkTime = true;
                                break;
                            }
                        }
                        if (!foundWorkTime) {
                            workTime.add(BigDecimal.ZERO);
                        }
                    }
                }
                // 过滤0工时
                if (filter != 2 || hasNonZeroWorkTime) {
                    userWorkTimeVO2.setWorkTime(workTime);
                    userWorkTimeVO.add(userWorkTimeVO2);
                }
            }
            returnList.add(userWorkTimeVO);


            returnList.add(nickName);
            // 重组返回数据结构
            for (String name : pmProjectName) {
                ProjectWorkTimeVO projectWorkTimeVO = new ProjectWorkTimeVO();
                projectWorkTimeVO.setProjectOrPerson(name);
                List<BigDecimal> workTime = new ArrayList<>();
                boolean hasNonZeroWorkTime = false;
                if (userAndProject.isEmpty()) {
                    for (String currentNickName : nickName) {
                        workTime.add(BigDecimal.ZERO);
                    }
                } else {
                    for (String currentNickName : nickName) {
                        boolean foundWorkTime = false;
                        for (WorkHoursStatisticsVO workHoursStatisticsVO : userAndProject) {
                            String userNickName = workHoursStatisticsVO.getNickName();
                            String projectName = workHoursStatisticsVO.getProjectName();
                            BigDecimal userProjectWorkTime = workHoursStatisticsVO.getWorkTime();
                            if (projectName == name && userNickName == currentNickName) {
                                workTime.add(userProjectWorkTime);
                                if (userProjectWorkTime.compareTo(BigDecimal.ZERO) != 0) {
                                    hasNonZeroWorkTime = true;
                                }
                                foundWorkTime = true;
                                break;
                            }
                        }
                        if (!foundWorkTime) {
                            workTime.add(BigDecimal.ZERO);
                        }
                    }
                }
                // 过滤0工时
                if (filter != 2 || hasNonZeroWorkTime) {
                    projectWorkTimeVO.setWorkTime(workTime);
                    projectWorkTime.add(projectWorkTimeVO);
                }
            }
            returnList.add(projectWorkTime);
        }
        return returnList;
    }

    /**
     * 工时-明细-导出
     * @return
     */
    @DataScope(deptAlias = "u")
    @Override
    public List<WorkTimeExportVO> workHourStatisticExport(PmWorkHourStatisticRequestVO requestVO) {
        List<Long> userIds = new ArrayList<>();
        if (Objects.isNull(requestVO.getUserIds()) || requestVO.getUserIds().isEmpty()) {
            userIds.add(SecurityUtils.getUserId());
            requestVO.setUserIds(userIds);
        }
        return pmWorkContentMapper.workHourStatisticExport(requestVO);
    }

    /**
     * 工时-统计-导出
     * @param userId
     * @param projectId
     * @param startDate
     * @param endDate
     * @return
     */
    @DataScope
    @Override
    public List<WorkTimeExportTwoVO> workHourExport(Long userId, Integer projectId, Integer filter, String
            startDate, String endDate, Integer workerOrProject) {
        return Collections.emptyList();
    }

}
