package com.ruoyi.oa.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.oa.domain.*;
import com.ruoyi.oa.domain.bo.BatchBo;
import com.ruoyi.oa.domain.dto.NodeDTO;
import com.ruoyi.oa.domain.dto.PersonalReportDTO;
import com.ruoyi.oa.domain.vo.OaExpressVo;
import com.ruoyi.oa.mapper.*;
import com.ruoyi.oa.mapper.OaProjectReportMapper;
import com.ruoyi.oa.mapper.SysOaTaskMapper;
import com.ruoyi.oa.mapper.OaUserActiveMapper;
import com.ruoyi.oa.mapper.OaExpressQuestionMapper;
import com.ruoyi.oa.mapper.OaRequirementsMapper;
import com.ruoyi.oa.service.IOaExpressService;
import com.ruoyi.oa.service.ISysOaTaskService;
import com.ruoyi.system.mapper.SysUserMapper;

import java.math.BigDecimal;
import java.util.Date;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.ruoyi.oa.domain.bo.OaProjectScheduleStepBo;
import com.ruoyi.oa.domain.vo.OaProjectScheduleStepVo;
import com.ruoyi.oa.service.IOaProjectScheduleStepService;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 项目进度步骤跟踪Service业务层处理
 *
 * @author hdka
 * @date 2025-05-08
 */
@RequiredArgsConstructor
@Service
public class OaProjectScheduleStepServiceImpl implements IOaProjectScheduleStepService {

    private final OaProjectScheduleStepMapper baseMapper;

    private final OaBonusPoolMapper bonusPoolMapper;

    private final OaProjectScheduleMapper scheduleMapper;

    private final SysUserMapper sysUserMapper;

    private  final OaBonusProjectRelMapper bonusProjectRelMapper;

    private  final SysOaProjectMapper projectMapper;

    private  final OaProjectScheduleMapper projectScheduleMapper;

    private final OaProjectScheduleStepMapper projectScheduleStepMapper;

    private final ISysOaTaskService sysOaTaskService;
    
    private final OaProjectReportMapper projectReportMapper;
    
    private final SysOaTaskMapper taskMapper;
    
    private final OaUserActiveMapper userActiveMapper;
    
    private final OaExpressQuestionMapper expressQuestionMapper;
    
    private final OaRequirementsMapper requirementsMapper;

    private final IOaExpressService oaExpressService;



    /**
     * 查询项目进度步骤跟踪
     */
    @Override
    public OaProjectScheduleStepVo queryById(Long trackId){
        return baseMapper.selectVoPlusById(trackId, LoginHelper.getUserId());
    }

    /**
     * 查询项目进度步骤跟踪列表
     */
    @Override
    public TableDataInfo<OaProjectScheduleStepVo> queryPageList(OaProjectScheduleStepBo bo, PageQuery pageQuery) {
        QueryWrapper<OaProjectScheduleStep> lqw = buildQueryWrapper(bo);
        Page<OaProjectScheduleStepVo> result = baseMapper.selectVoPagePlus(pageQuery.build(), lqw,LoginHelper.getUserId());
        return TableDataInfo.build(result);
    }
    @Override
    public TableDataInfo<OaProjectScheduleStepVo> queryPageListPage(OaProjectScheduleStepBo bo, PageQuery pageQuery) {
        QueryWrapper<OaProjectScheduleStep> lqw = buildQueryWrapper(bo);
        Page<OaProjectScheduleStepVo> result = baseMapper.selectVoPageNew(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询项目进度步骤跟踪列表
     */
    @Override
    public List<OaProjectScheduleStepVo> queryList(OaProjectScheduleStepBo bo) {
        QueryWrapper<OaProjectScheduleStep> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private QueryWrapper<OaProjectScheduleStep> buildQueryWrapper(OaProjectScheduleStepBo bo) {
        Map<String, Object> params = bo.getParams();
        QueryWrapper<OaProjectScheduleStep> lqw = Wrappers.query();
        lqw.eq("opss.use_flag", 1);
        lqw.eq(bo.getScheduleId() != null, "opss.schedule_id", bo.getScheduleId());
        lqw.eq("opss.del_flag", 0);
        lqw.eq(bo.getStepOrder() != null, "opss.step_order", bo.getStepOrder());
        lqw.like(StringUtils.isNotBlank(bo.getStepName()), "opss.step_name", bo.getStepName());
        lqw.eq(bo.getStatus() != null, "opss.status", bo.getStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getNodeHeader()), "opss.node_header", bo.getNodeHeader());
        lqw.eq(bo.getSupplierId() != null, "opss.supplier_id", bo.getSupplierId());
        //根据开始时间和结束时间作为范围判断planEnd
        lqw.ge(bo.getStartTime() != null, "opss.plan_end", bo.getStartTime());
        lqw.le(bo.getEndTime() != null, "opss.plan_end", bo.getEndTime());
        return lqw;
    }

    /**
     * 新增项目进度步骤跟踪
     */
    @Override
    public Boolean insertByBo(OaProjectScheduleStepBo bo) {
        OaProjectScheduleStep add = BeanUtil.toBean(bo, OaProjectScheduleStep.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setTrackId(add.getTrackId());
        }
        return flag;
    }

    /**
     * 修改项目进度步骤跟踪
     */
    @Override
    public Boolean updateByBo(OaProjectScheduleStepBo bo) {
        // 1. 转换实体并校验
        OaProjectScheduleStep update = BeanUtil.toBean(bo, OaProjectScheduleStep.class);
        validEntityBeforeSave(update);

        // 2. 查询原数据（先判断 trackId 是否存在）
        Long trackId = update.getTrackId();
        if (trackId == null) {
            throw new IllegalArgumentException("更新主键 trackId 不能为空");
        }
        OaProjectScheduleStep original = baseMapper.selectById(trackId); // 推荐用 selectById 更简洁
        if (original == null) {
            // 处理查询不到的情况（例如抛异常或返回失败）
            throw new RuntimeException("未找到 ID 为 " + trackId + " 的项目进度步骤记录");
        }

        // 3. 处理结束时间逻辑（此时 original 一定非 null，可安全调用方法）
        if (original.getEndTime() == null) {
            // 首次修改：设置结束时间和原始结束时间
            update.setEndTime(bo.getEndTime());
            update.setOriginalEndTime(bo.getEndTime());
        }

        // 4. 执行更新
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(OaProjectScheduleStep entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除项目进度步骤跟踪
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }
    @Override
    public Boolean deleteByScheduleIds(Collection<Long> scheduleIds, Boolean isValid) {
        if (isValid) {
            // 如需校验，添加业务校验逻辑（例如：判断步骤是否存在关联数据等）
        }
        return projectScheduleStepMapper.deleteByScheduleIds(scheduleIds) > 0;
    }

    @Override
    public OaProjectScheduleStepVo maxStepByScheduleId(Long scheduleId) {
        return baseMapper.maxStepByScheduleId(scheduleId);
    }

    @Override
    public void updateByStepAndScheduleId(Long currentStep, Long scheduleId) {

        baseMapper.updateByStepAndScheduleId(currentStep,scheduleId);
    }

    @Override
    public OaProjectScheduleStepVo selectByCurrentStepAndScheduleId(Long currentStep, Long scheduleId) {
        return baseMapper.selectByCurrentStepAndScheduleId(currentStep,scheduleId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int changeBatch(BatchBo batchBo) {
        List<OaProjectScheduleStepBo> boList = batchBo.getBoList();
        OaProjectScheduleStepBo oaProjectScheduleStepBo = boList.get(0);
        LambdaQueryWrapper<OaProjectScheduleStep> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OaProjectScheduleStep::getScheduleId, oaProjectScheduleStepBo.getScheduleId());
        wrapper.eq(OaProjectScheduleStep::getUseFlag, 1L);
        List<OaProjectScheduleStep> oaProjectScheduleSteps = baseMapper.selectList(wrapper);
        Long batchId = 1L;
        // 首先将上一批次的全部关闭
        for (OaProjectScheduleStep oaProjectScheduleStep : oaProjectScheduleSteps) {
            oaProjectScheduleStep.setUseFlag(0L);
            System.out.println(oaProjectScheduleStep);
            baseMapper.updateById(oaProjectScheduleStep);
            batchId = oaProjectScheduleStep.getBatchId();
        }


        OaProjectSchedule oaProjectSchedule = new OaProjectSchedule();
        oaProjectSchedule.setScheduleId(oaProjectScheduleStepBo.getScheduleId());
        oaProjectSchedule.setCurrentStep(batchBo.getCurrentStep());
        scheduleMapper.updateById(oaProjectSchedule);
        // 新批次进入
        int flag = 0;
        batchId = batchId+1;
        for (OaProjectScheduleStepBo projectScheduleStepBo : boList) {
            projectScheduleStepBo.setTrackId(null);
            projectScheduleStepBo.setUseFlag(1L);
            projectScheduleStepBo.setScheduleId(oaProjectScheduleStepBo.getScheduleId());
            projectScheduleStepBo.setBatchId(batchId);

            // 将新增后的
            if (projectScheduleStepBo.getStepOrder()> batchBo.getCurrentStep()){
                projectScheduleStepBo.setActualStart(null);
                projectScheduleStepBo.setActualEnd(null);
                projectScheduleStepBo.setStatus(0L);
            }

            // 将新增后的
            if (Objects.equals(projectScheduleStepBo.getStepOrder(), batchBo.getCurrentStep())){
                projectScheduleStepBo.setActualStart(new Date());
                projectScheduleStepBo.setActualEnd(null);
                projectScheduleStepBo.setStatus(0L);
            }
            this.insertByBo(projectScheduleStepBo);
            flag =1;
        }

        return flag;
    }


    /**
     * 批量插入节点数据（按表结构约束设置字段值）
     * @param nodeList 代码中定义的表格节点数据（需包含tab、一二级节点和规范说明）
     * @param scheduleId 所属项目进度ID（非空，必须传入）
     */
    public void batchInsertNodes(List<NodeDTO> nodeList, Long scheduleId) {
        // 步骤序号从1开始递增（确保与schedule_id、use_flag、batch_id组合唯一）
        AtomicInteger stepOrder = new AtomicInteger(1);

        List<OaProjectScheduleStep> entities = nodeList.stream().map(node -> {
            OaProjectScheduleStep step = new OaProjectScheduleStep();

            // 1. 必须设置值的四个核心字段
            step.setTabNode(node.getTabNode());                  // tab节点
            step.setFirstLevelNode(node.getFirstLevelNode());    // 一级节点
            step.setSecondLevelNode(node.getSecondLevelNode());  // 二级节点
            step.setSpecification(node.getSpecification());      // 规范说明（从NodeDTO补充此字段）

            // 2. 表结构中非空字段（必须设置，否则插入失败）
            step.setScheduleId(scheduleId);      // 所属项目进度ID（非空，外部传入）
            step.setStepOrder((long) stepOrder.getAndIncrement());      // 步骤序号（非空，递增生成）
            step.setStepName(node.getStepName());// 步骤名称（非空，从NodeDTO获取，建议用二级节点名）
            step.setSortNum(node.getSortNum());
            step.setCreateTime(new Date());
            return step;
        }).collect(Collectors.toList());

        // 批量插入数据库
        baseMapper.saveBatch(entities);
    }
    //查询进度负责人负责了多少进度以及完成度是多少0进行中 1待验收 2已完成 是否延期用比较end_time和original_end_time的大小
    //如果前者大于后者则表示延期
    @Override
    public List<Map<String, Object>> queryProgressByHeader() {
        // 构建查询条件：只查询未删除且正在使用的记录
        LambdaQueryWrapper<OaProjectScheduleStep> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(OaProjectScheduleStep::getDelFlag, 0)
                .eq(OaProjectScheduleStep::getUseFlag, 1);

        // 查询所有相关记录
        List<OaProjectScheduleStep> steps = baseMapper.selectList(wrapper);

        // 按负责人(header)分组统计
        Map<String, List<OaProjectScheduleStep>> headerGrouped = steps.stream()
                .filter(step -> step.getHeader() != null && !step.getHeader().isEmpty())
                .collect(Collectors.groupingBy(OaProjectScheduleStep::getHeader));

        // 构造返回结果
        List<Map<String, Object>> result = new ArrayList<>();
        for (Map.Entry<String, List<OaProjectScheduleStep>> entry : headerGrouped.entrySet()) {
            String header = entry.getKey();
            List<OaProjectScheduleStep> headerSteps = entry.getValue();

            long total = headerSteps.size(); // 总进度数
            long completed = headerSteps.stream()
                    .mapToLong(step -> step.getStatus() == null ? 0L : step.getStatus())
                    .filter(status -> status == 2) // 状态为"已完成"
                    .count();
            // 对待验收状态的统计
            long pendingAcceptance = headerSteps.stream()
                    .mapToLong(step -> step.getStatus() == null ? 0L : step.getStatus())
                    .filter(status -> status == 1) // 状态为"待验收"
                    .count();

            long delayed = headerSteps.stream()
                    .filter(step -> step.getEndTime() != null && step.getOriginalEndTime() != null)
                    .filter(step -> step.getEndTime().isAfter(step.getOriginalEndTime()))
                    .count();

            Map<String, Object> item = new HashMap<>();
            item.put("header", header);
            item.put("total", total);
            item.put("completed", completed);
            item.put("pendingAcceptance", pendingAcceptance);
            item.put("delayed", delayed);
            result.add(item);
        }

        return result;
    }

    /**
     * 个人报表接口：根据昵称和奖金池ID查询个人信息、负责项目及进度统计
     * @param nickName 用户名（昵称）
     * @param poolId 奖金池ID
     * @return 包含个人信息、负责项目、进度统计的结果
     */
    @Override
    public PersonalReportDTO personalReport(Long poolId, String nickName) {
        // 查询奖金池信息（获取开始时间和结束时间）
        OaBonusPool bonusPool = bonusPoolMapper.selectById(poolId);
        if (bonusPool == null) {
            throw new RuntimeException("未找到奖金池：" + poolId);
        }
        Date startTime = bonusPool.getStartDate();
        Date endTime = bonusPool.getEndDate();
        // 查询用户基本信息
        SysUser user = sysUserMapper.selectOne(
                Wrappers.<SysUser>lambdaQuery()
                        .eq(SysUser::getNickName, nickName)
                        .eq(SysUser::getDelFlag, "0")
        );
        if (user == null) {
            throw new RuntimeException("未找到用户：" + nickName);
        }
        Long userId = user.getUserId();

        // 查询奖金池关联的项目ID
        List<OaBonusProjectRel> rels = bonusProjectRelMapper.selectList(
                Wrappers.<OaBonusProjectRel>lambdaQuery()
                        .eq(OaBonusProjectRel::getPoolId, poolId)
                        .eq(OaBonusProjectRel::getDelFlag, "0")
        );
        List<Long> projectIds = CollUtil.isEmpty(rels)
                ? Collections.emptyList()
                : rels.stream().map(OaBonusProjectRel::getProjectId).collect(Collectors.toList());

        // 筛选用户负责的项目
        List<SysOaProject> responsibleProjects = projectMapper.selectList(
                Wrappers.<SysOaProject>lambdaQuery()
                        .in(SysOaProject::getProjectId, projectIds)
                        .eq(SysOaProject::getFunctionary, nickName)
        );

        // 查询用户负责的进度步骤（核心数据），并关联项目ID
        List<OaProjectScheduleStep> userSteps = new ArrayList<>();
        // 存储 scheduleId 与 projectId 的映射关系（关键：通过进度主表关联项目ID）
        Map<Long, Long> scheduleProjectMap = new HashMap<>();

        if (CollUtil.isNotEmpty(projectIds)) {
            // 查询关联项目的进度主表，并构建 scheduleId -> projectId 映射
            List<OaProjectSchedule> schedules = projectScheduleMapper.selectList(
                    Wrappers.<OaProjectSchedule>lambdaQuery()
                            .in(OaProjectSchedule::getProjectId, projectIds)
                            .eq(OaProjectSchedule::getDelFlag, "0")
            );
            if (CollUtil.isNotEmpty(schedules)) {
                // 构建映射：进度ID -> 项目ID
                scheduleProjectMap = schedules.stream()
                        .filter(Objects::nonNull)
                        .filter(s -> s.getScheduleId() != null && s.getProjectId() != null)
                        .collect(Collectors.toMap(
                                OaProjectSchedule::getScheduleId,
                                OaProjectSchedule::getProjectId,
                                (existing, replacement) -> existing // 若有重复ID，保留第一个
                        ));

                List<Long> scheduleIds = new ArrayList<>(scheduleProjectMap.keySet());

                // 查询用户负责的进度步骤
                userSteps = projectScheduleStepMapper.selectList(
                        Wrappers.<OaProjectScheduleStep>lambdaQuery()
                                .in(OaProjectScheduleStep::getScheduleId, scheduleIds)
                                .eq(OaProjectScheduleStep::getNodeHeader, nickName)
                                .eq(OaProjectScheduleStep::getDelFlag, "0")
                                .eq(OaProjectScheduleStep::getUseFlag, 1)
                                .between(OaProjectScheduleStep::getUpdateTime, startTime, endTime)  // 时间范围筛选
                );

                // 为每个步骤设置对应的项目ID
                for (OaProjectScheduleStep step : userSteps) {
                    if (step != null && step.getScheduleId() != null) {
                        // 从映射中获取当前步骤所属的项目ID
                        Long projectId = scheduleProjectMap.get(step.getScheduleId());
                        step.setProjectId(projectId);
                    }
                }
            }
        }

        // 统计进度数据
        PersonalReportDTO.ProgressStats progressStats = new PersonalReportDTO.ProgressStats();
        progressStats.setTotal((long) userSteps.size());
        progressStats.setCompleted(userSteps.stream()
                .filter(step -> step.getStatus() != null && step.getStatus() == 2)
                .count());
        progressStats.setPendingAcceptance(userSteps.stream()
                .filter(step -> step.getStatus() != null && step.getStatus() == 1)
                .count());
        progressStats.setDelayed(userSteps.stream()
                .filter(step -> step.getEndTime() != null && step.getOriginalEndTime() != null)
                .filter(step -> step.getEndTime().isAfter(step.getOriginalEndTime()))
                .count());
        // 查询用户相关任务
        List<SysOaTask> tasks = sysOaTaskService.getTasksByNicknameAndProjectIds(nickName, projectIds,startTime, endTime);
        // 封装返回DTO
        PersonalReportDTO result = new PersonalReportDTO();
        result.setUserInfo(user);
        result.setResponsibleProjects(responsibleProjects);
        result.setProgressStats(progressStats);
        result.setUserSteps(userSteps); // 此时userSteps已包含每个步骤对应的projectId
        result.setTasks(tasks);
        // 统计活跃天数
        result.setActiveDays(getActiveDays(userId, startTime, endTime));
        // 1. 统计报工信息
        result.setWorkReportStats(getWorkReportStats(userId, startTime, endTime));

        // 2. 统计出差信息
        result.setBusinessTripStats(getBusinessTripStats(userId, startTime, endTime));

        // 3. 统计项目信息
        result.setProjectStats(getProjectStats(userId, nickName, startTime, endTime));

//        // 4. 统计进度信息
//        result.setProgressStats(getProgressStats(nickName, startDate, endDate));

        // 5. 统计任务信息
        result.setTaskStats(getTaskStats(userId, startTime, endTime));

        // 6. 统计工程异常信息
        result.setExceptionStats(getExceptionStats(nickName, startTime, endTime));

        // 7. 统计关键采购任务信息
        result.setProcurementStats(getProcurementStats(userId, startTime, endTime));

        return result;
    }

    /**
     * 统计用户活跃天数
     * @param userId 用户ID
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 活跃天数
     */
    private Integer getActiveDays(Long userId, Date startDate, Date endDate) {
        // 构建查询条件
        LambdaQueryWrapper<OaUserActive> wrapper = Wrappers.<OaUserActive>lambdaQuery()
                .eq(OaUserActive::getUserId, userId)
                .eq(OaUserActive::getDelFlag, 0);

        // 添加时间范围条件
        if (startDate != null && endDate != null) {
            wrapper.between(OaUserActive::getActiveDate, startDate, endDate);
        }

        // 查询活跃记录数量
        Long count = userActiveMapper.selectCount(wrapper);

        return count != null ? count.intValue() : 0;
    }
    
    /**
     * 统计报工信息
     */
    private PersonalReportDTO.WorkReportStats getWorkReportStats(Long userId, Date startDate, Date endDate) {
        PersonalReportDTO.WorkReportStats stats = new PersonalReportDTO.WorkReportStats();
        
        LambdaQueryWrapper<OaProjectReport> wrapper = Wrappers.<OaProjectReport>lambdaQuery()
            .eq(OaProjectReport::getDelFlag, 0)
            .eq(OaProjectReport::getUserId, userId);
        
        // 添加时间范围条件
        if (startDate != null && endDate != null) {
            wrapper.between(OaProjectReport::getCreateTime, startDate, endDate);
        }
        
        List<OaProjectReport> reports = projectReportMapper.selectList(wrapper);
        
        // 计算报工天数（这里简化处理，实际可能需要按日期去重）
        stats.setTotalWorkDays(BigDecimal.valueOf(reports.size()));
        stats.setValidWorkDays(BigDecimal.valueOf(reports.size()));
        
        // 统计涉及的项目数量
        Set<Long> projectIds = reports.stream()
            .map(OaProjectReport::getProjectId)
            .filter(Objects::nonNull)
            .collect(Collectors.toSet());
        stats.setReportProjectCount(projectIds.size());
        
        return stats;
    }
    
    /**
     * 统计出差信息
     */
    private PersonalReportDTO.BusinessTripStats getBusinessTripStats(Long userId, Date startDate, Date endDate) {
        PersonalReportDTO.BusinessTripStats stats = new PersonalReportDTO.BusinessTripStats();
        
        LambdaQueryWrapper<OaProjectReport> wrapper = Wrappers.<OaProjectReport>lambdaQuery()
            .eq(OaProjectReport::getDelFlag, 0)
            .eq(OaProjectReport::getIsTrip, 1) // 出差标记
            .eq(OaProjectReport::getUserId, userId);
        
        // 添加时间范围条件
        if (startDate != null && endDate != null) {
            wrapper.between(OaProjectReport::getCreateTime, startDate, endDate);
        }


        // 1. 统计总出差天数（按记录数统计，假设一条记录对应一天）
        Long totalTripCount = projectReportMapper.selectCount(wrapper);
        stats.setTotalTripDays(BigDecimal.valueOf(totalTripCount));

        // 国外
        LambdaQueryWrapper<OaProjectReport> foreignWrapper = Wrappers.<OaProjectReport>lambdaQuery()
                .eq(OaProjectReport::getDelFlag, 0)
                .eq(OaProjectReport::getIsTrip, 1)
                .eq(OaProjectReport::getUserId, userId)
                .eq(OaProjectReport::getWorkType, 1); // 国外标志
        if (StringUtils.isNull(startDate) && StringUtils.isNull(endDate)) {
            foreignWrapper.between(OaProjectReport::getCreateTime, startDate, endDate);
        }
        Long foreignTripCount = projectReportMapper.selectCount(foreignWrapper);
        stats.setForeignTripDays(BigDecimal.valueOf(foreignTripCount));

        // 3. 国内出差天数 = 总出差天数 - 国外出差天数
        stats.setDomesticTripDays(BigDecimal.valueOf(totalTripCount - foreignTripCount));
        
        // 统计出差项目数量
        Set<Long> tripProjectIds = projectReportMapper.selectObjs(wrapper
                .select(OaProjectReport::getProjectId)) // 只查询project_id字段
                .stream()
                .filter(Objects::nonNull)
                .map(obj -> (Long) obj)
                .collect(Collectors.toSet());
        stats.setTripProjectCount(tripProjectIds.size());
        
        return stats;
    }
    
    /**
     * 统计项目信息
     */
    private PersonalReportDTO.ProjectStats getProjectStats(Long userId, String nickName, Date startDate, Date endDate) {
        PersonalReportDTO.ProjectStats stats = new PersonalReportDTO.ProjectStats();
        
        // 通过报工记录查询参与的项目
        LambdaQueryWrapper<OaProjectReport> reportWrapper = Wrappers.<OaProjectReport>lambdaQuery()
            .eq(OaProjectReport::getUserId, userId)
            .eq(OaProjectReport::getDelFlag, 0);
            
//        if (startDate != null && endDate != null) {
//            reportWrapper.between(OaProjectReport::getCreateTime, startDate, endDate);
//        }
        
        List<OaProjectReport> reports = projectReportMapper.selectList(reportWrapper);
        Set<Long> participatedProjectIds = reports.stream()
            .map(OaProjectReport::getProjectId)
            .filter(Objects::nonNull)
            .collect(Collectors.toSet());
        
        // 查询负责的项目
        LambdaQueryWrapper<SysOaProject> projectWrapper = Wrappers.<SysOaProject>lambdaQuery()
            .eq(SysOaProject::getFunctionary, nickName);
        List<SysOaProject> responsibleProjectList = projectMapper.selectList(projectWrapper);
        
        stats.setTotalProjects(participatedProjectIds.size());
        stats.setResponsibleProjects(responsibleProjectList.size());
        stats.setParticipatedProjects(participatedProjectIds.size());
        
        // 构建项目清单
        List<PersonalReportDTO.ProjectSummary> projectList = new ArrayList<>();
        
        // 添加负责的项目
        for (SysOaProject project : responsibleProjectList) {
            PersonalReportDTO.ProjectSummary summary = new PersonalReportDTO.ProjectSummary();
            summary.setProjectId(project.getProjectId());
            summary.setProjectName(project.getProjectName());
            summary.setProjectNum(project.getProjectNum());
            summary.setRole("负责人");
            
            // 计算参与天数
            //TODO 项目负责人是不报工的
            long participationDays = reports.stream()
                .filter(report -> project.getProjectId().equals(report.getProjectId()))
                .count();
            summary.setParticipationDays(BigDecimal.valueOf(participationDays));
            
            projectList.add(summary);
        }
        
        // 添加参与的其他项目
        for (Long projectId : participatedProjectIds) {
            if (responsibleProjectList.stream().noneMatch(p -> p.getProjectId().equals(projectId))) {
                SysOaProject project = projectMapper.selectById(projectId);
                if (project != null) {
                    PersonalReportDTO.ProjectSummary summary = new PersonalReportDTO.ProjectSummary();
                    summary.setProjectId(project.getProjectId());
                    summary.setProjectName(project.getProjectName());
                    summary.setProjectNum(project.getProjectNum());
                    summary.setRole("参与者");
                    
                    // 计算参与天数
                    long participationDays = reports.stream()
                        .filter(report -> projectId.equals(report.getProjectId()))
                        .count();
                    summary.setParticipationDays(BigDecimal.valueOf(participationDays));
                    
                    projectList.add(summary);
                }
            }
        }
        
        stats.setProjectList(projectList);
        return stats;
    }
    

    
    /**
     * 统计任务信息
     */
    private PersonalReportDTO.TaskStats getTaskStats(Long userId, Date startDate, Date endDate) {
        PersonalReportDTO.TaskStats stats = new PersonalReportDTO.TaskStats();
        
        // 查询发放的任务（创建的任务）
        LambdaQueryWrapper<SysOaTask> assignedWrapper = Wrappers.<SysOaTask>lambdaQuery()
            .eq(SysOaTask::getCreateUserId, userId);
            
        if (startDate != null && endDate != null) {
            assignedWrapper.between(SysOaTask::getBeginTime, startDate, endDate);
        }
        
        List<SysOaTask> assignedTasks = taskMapper.selectList(assignedWrapper);
        
        // 查询承担的任务（被分配的任务）
        LambdaQueryWrapper<SysOaTask> undertakenWrapper = Wrappers.<SysOaTask>lambdaQuery()
            .eq(SysOaTask::getWorkerId, userId);
            
        if (startDate != null && endDate != null) {
            undertakenWrapper.between(SysOaTask::getBeginTime, startDate, endDate);
        }
        
        List<SysOaTask> undertakenTasks = taskMapper.selectList(undertakenWrapper);
        
        // 统计数量
        stats.setAssignedTasks(assignedTasks.size());
        stats.setUndertakenTasks(undertakenTasks.size());
        
        // 统计已完成任务数量（状态为完成）
        long completedAssigned = assignedTasks.stream().filter(task -> Long.valueOf(2).equals(task.getState())).count();
        long completedUndertaken = undertakenTasks.stream().filter(task -> Long.valueOf(2).equals(task.getState())).count();
        stats.setCompletedTasks((int) (completedAssigned + completedUndertaken));

        // 统计进行中任务数量(状态为 1 等待审核)
        long underwayAssigned = assignedTasks.stream().filter(task -> Long.valueOf(1).equals(task.getState())).count();
        long underwayUndertaken = undertakenTasks.stream().filter(task -> Long.valueOf(1).equals(task.getState())).count();
        stats.setUnderwayTasks((int) (underwayAssigned + underwayUndertaken));
        //未完成的数量
        long unfinishedAssigned = assignedTasks.stream().filter(task -> Long.valueOf(0).equals(task.getState())).count();
        long unfinishedUndertaken = undertakenTasks.stream().filter(task -> Long.valueOf(0).equals(task.getState())).count();
        stats.setUnfinishedTasks((int) (unfinishedAssigned + unfinishedUndertaken));
        
        // 统计延期任务数量
        long delayedAssigned = assignedTasks.stream().filter(task -> Long.valueOf(15).equals(task.getState())).count();
        long delayedUndertaken = undertakenTasks.stream().filter(task -> Long.valueOf(15).equals(task.getState())).count();
        stats.setDelayedTasks((int) (delayedAssigned + delayedUndertaken));
        
        // 构建任务清单
        List<PersonalReportDTO.TaskSummary> assignedTaskList = assignedTasks.stream()
            .map(this::buildTaskSummary)
            .collect(Collectors.toList());
        
        List<PersonalReportDTO.TaskSummary> undertakenTaskList = undertakenTasks.stream()
            .map(this::buildTaskSummary)
            .collect(Collectors.toList());
        
        stats.setAssignedTaskList(assignedTaskList);
        stats.setUndertakenTaskList(undertakenTaskList);
        
        return stats;
    }
    
    /**
     * 构建任务摘要
     */
    private PersonalReportDTO.TaskSummary buildTaskSummary(SysOaTask task) {
        PersonalReportDTO.TaskSummary summary = new PersonalReportDTO.TaskSummary();
        summary.setTaskId(task.getTaskId());
        summary.setTaskTitle(task.getTaskTitle());
        summary.setState(task.getState());
        summary.setIsDelayed(task.getPostponements() != null && task.getPostponements() > 0);
        summary.setPostponements(task.getPostponements());
        
        // 获取项目名称
        if (task.getProjectId() != null) {
            SysOaProject project = projectMapper.selectById(task.getProjectId());
            if (project != null) {
                summary.setProjectName(project.getProjectName());
            }
        }
        
        return summary;
    }
    
    /**
     * 统计工程异常信息（基于oa_express_question表）
     */
    private PersonalReportDTO.EngineeringExceptionStats getExceptionStats(String nickName, Date startDate, Date endDate) {
        PersonalReportDTO.EngineeringExceptionStats stats = new PersonalReportDTO.EngineeringExceptionStats();

        
        // 查询快递问题表，通过汇报人匹配
        LambdaQueryWrapper<OaExpressQuestion> wrapper = Wrappers.<OaExpressQuestion>lambdaQuery()
            .eq(OaExpressQuestion::getReportBy, nickName)
            .eq(OaExpressQuestion::getDelFlag, 0);
            //type feedback vachar 默认值叫feedback
        // 添加时间范围条件（基于汇报时间）
        if (startDate != null && endDate != null) {
            wrapper.between(OaExpressQuestion::getReportTime, startDate, endDate);
        }
        
        List<OaExpressQuestion> questions = expressQuestionMapper.selectList(wrapper);
        
        stats.setTotalExceptions(questions.size());
        
        // 统计已解决和未解决的异常
        long resolvedCount = questions.stream().filter(q -> Long.valueOf(1).equals(q.getStatus())).count();
        long unresolvedCount = questions.stream().filter(q -> Long.valueOf(0).equals(q.getStatus())).count();
        
        stats.setResolvedExceptions((int) resolvedCount);
        stats.setDelayedExceptions((int) unresolvedCount); // 未解决的视为延期异常
        
        // 构建异常清单
        List<PersonalReportDTO.ExceptionSummary> exceptionList = questions.stream()
            .map(question -> {
                PersonalReportDTO.ExceptionSummary summary = new PersonalReportDTO.ExceptionSummary();
                summary.setExceptionId(question.getQuestionId());
                summary.setDescription(question.getDescription());
                summary.setStatus(Long.valueOf(1).equals(question.getStatus()) ? "已解决" : "未解决");
                summary.setIsDelayed(Long.valueOf(0).equals(question.getStatus())); // 未解决的视为延期
                
                // 这里可以根据expressId关联获取项目信息
                summary.setProjectName(oaExpressService.queryById(question.getExpressId()).getProjectName());
                
                return summary;
            })
            .collect(Collectors.toList());
        
        stats.setExceptionList(exceptionList);
        return stats;
    }
    
    /**
     * 统计关键采购任务信息（基于oa_requirements表）
     */
    private PersonalReportDTO.ProcurementTaskStats getProcurementStats(Long userId, Date startDate, Date endDate) {
        PersonalReportDTO.ProcurementTaskStats stats = new PersonalReportDTO.ProcurementTaskStats();
        
        // 查询需求表，通过负责人ID匹配
        LambdaQueryWrapper<OaRequirements> wrapper = Wrappers.<OaRequirements>lambdaQuery()
            .eq(OaRequirements::getOwnerId, userId)
            .eq(OaRequirements::getDelFlag, 0);
                
        // 添加时间范围条件
        if (startDate != null && endDate != null) {
            wrapper.between(OaRequirements::getCreateTime, startDate, endDate);
        }
        
        List<OaRequirements> requirements = requirementsMapper.selectList(wrapper);
        
        stats.setTotalProcurementTasks(requirements.size());
        
        // 统计已完成和延期的需求
        long completedCount = requirements.stream().filter(req -> Integer.valueOf(1).equals(req.getStatus())).count();
        stats.setCompletedProcurementTasks((int) completedCount);
        
        // 计算延期需求（截止日期已过但未完成的）
        long delayedCount = requirements.stream()
            .filter(req -> Integer.valueOf(0).equals(req.getStatus())) // 未完成
            .filter(req -> req.getDeadline() != null && req.getDeadline().before(new Date())) // 已过期
            .count();
        stats.setDelayedProcurementTasks((int) delayedCount);
        
        // 构建采购任务清单
        List<PersonalReportDTO.ProcurementTaskSummary> procurementList = requirements.stream()
            .map(req -> {
                PersonalReportDTO.ProcurementTaskSummary summary = new PersonalReportDTO.ProcurementTaskSummary();
                summary.setProcurementId(req.getRequirementId());
                summary.setProcurementContent(req.getTitle());
                summary.setStatus(Integer.valueOf(1).equals(req.getStatus()) ? "已完成" : "进行中");
                
                // 判断是否延期
                boolean isDelayed = Integer.valueOf(0).equals(req.getStatus()) && 
                    req.getDeadline() != null && req.getDeadline().before(new Date());
                summary.setIsDelayed(isDelayed);
                
                // 获取项目名称
                if (req.getProjectId() != null) {
                    SysOaProject project = projectMapper.selectById(req.getProjectId());
                    if (project != null) {
                        summary.setProjectName(project.getProjectName());
                    }
                } else {
                    summary.setProjectName("无关联项目");
                }
                
                return summary;
            })
            .collect(Collectors.toList());
        
        stats.setProcurementTaskList(procurementList);
        return stats;
    }

//    /**
//     * 统计进度信息
//     */
//    private PersonalReportDTO.ProgressStats getProgressStats(String nickName, String startDate, String endDate) {
//        PersonalReportDTO.ProgressStats stats = new PersonalReportDTO.ProgressStats();
//
//        // 查询用户负责的进度
//        LambdaQueryWrapper<OaProjectScheduleStep> wrapper = Wrappers.<OaProjectScheduleStep>lambdaQuery()
//                .eq(OaProjectScheduleStep::getNodeHeader, nickName)
//                .eq(OaProjectScheduleStep::getDelFlag, "0");
//
//        if (startDate != null && endDate != null) {
//            wrapper.between(OaProjectScheduleStep::getCreateTime, startDate, endDate);
//        }
//
//        List<OaProjectScheduleStep> steps = baseMapper.selectList(wrapper);
//
//        stats.setTotalProgress(steps.size());
//
//        // 统计各状态的进度数量
//        long completedCount = steps.stream().filter(step -> Long.valueOf(2).equals(step.getStatus())).count();
//        long inProgressCount = steps.stream().filter(step -> Long.valueOf(1).equals(step.getStatus())).count();
//
//        // 计算延期进度（实际结束时间晚于计划结束时间）
//        long delayedCount = steps.stream()
//                .filter(step -> step.getActualEnd() != null && step.getPlanEnd() != null)
//                .filter(step -> step.getActualEnd().after(step.getPlanEnd()))
//                .count();
//
//        stats.setCompletedProgress((int) completedCount);
//        stats.setInProgressCount((int) inProgressCount);
//        stats.setDelayedProgress((int) delayedCount);
//
//        // 构建进度清单
//        List<PersonalReportDTO.ProgressSummary> progressList = steps.stream()
//                .map(step -> {
//                    PersonalReportDTO.ProgressSummary summary = new PersonalReportDTO.ProgressSummary();
//                    summary.setTrackId(step.getTrackId());
//                    summary.setStepName(step.getStepName());
//                    summary.setStatus(step.getStatus());
//
//                    // 判断是否延期
//                    boolean isDelayed = step.getActualEnd() != null && step.getPlanEnd() != null &&
//                            step.getActualEnd().after(step.getPlanEnd());
//                    summary.setIsDelayed(isDelayed);
//
//                    // 获取项目名称
//                    if (step.getScheduleId() != null) {
//                        OaProjectSchedule schedule = scheduleMapper.selectById(step.getScheduleId());
//                        if (schedule != null && schedule.getProjectId() != null) {
//                            SysOaProject project = projectMapper.selectById(schedule.getProjectId());
//                            if (project != null) {
//                                summary.setProjectName(project.getProjectName());
//                            }
//                        }
//                    }
//
//                    return summary;
//                })
//                .collect(Collectors.toList());
//
//        stats.setProgressList(progressList);
//        return stats;
//    }


}
