package jnpf.cultivate.v2.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jnpf.base.entity.SuperBaseEntity;
import jnpf.base.vo.PageListVO;
import jnpf.cultivate.mapper.*;
import jnpf.cultivate.service.*;
import jnpf.cultivate.utils.*;
import jnpf.cultivate.v2.service.*;
import jnpf.cultivate.v2.util.CultivateBatchQueryUtil;
import jnpf.cultivate.v2.util.CultivateCourseStudyUtil;
import jnpf.entity.cultivate.CultivateIdentifyApply;
import jnpf.entity.cultivate.CultivateIdentifyApplyDetails;
import jnpf.entity.cultivate.TeachingRecord;
import jnpf.enums.cultivate.StudyStatsEnum;
import jnpf.enums.cultivate.task.TaskAssignmentRuleEnum;
import jnpf.enums.cultivate.v2.LearnTaskStatusEnum;
import jnpf.exception.DataException;
import jnpf.model.cultivate.CultivatePage;
import jnpf.model.cultivate.dto.learn.BatchCommonCountDto;
import jnpf.model.cultivate.dto.learn.FtbCultivateLearnAllocationDTO;
import jnpf.model.cultivate.dto.learn.NeedAlertUserDto;
import jnpf.model.cultivate.po.certificate.FtbCertificateUserEntity;
import jnpf.model.cultivate.po.common.FtbCultivateCoverInfoEntity;
import jnpf.model.cultivate.po.exam.FtbCultivateExamUser;
import jnpf.model.cultivate.po.learn.*;
import jnpf.model.cultivate.po.position.FtbCultivatePositionCourceLearning;
import jnpf.model.cultivate.po.task.FtbCultivateLearnTaskPhase;
import jnpf.model.cultivate.po.task.FtbCultivateLearnTaskPractice;
import jnpf.model.cultivate.po.task.FtbCultivateTaskLog;
import jnpf.model.cultivate.v2.course.vo.app.V2ChapterVo;
import jnpf.model.cultivate.v2.enums.PositionBusinessSourceEnum;
import jnpf.model.cultivate.v2.position.req.V2CultivateCoursePageReq;
import jnpf.model.cultivate.v2.position.vo.V2CultivateJobLearnCourseVo;
import jnpf.model.cultivate.v2.statistics.V2UserLearningStatusResult;
import jnpf.model.cultivate.v2.task.req.V2CultivateLearnTaskListForManagerReq;
import jnpf.model.cultivate.v2.task.req.V2CultivateTaskSaveReq;
import jnpf.model.cultivate.v2.task.req.V2MyCultivateTaskListForReq;
import jnpf.model.cultivate.v2.task.vo.*;
import jnpf.model.cultivate.vo.learn.info.TimeDifference;
import jnpf.model.enums.SelfrowingEnum;
import jnpf.model.personnels.dto.roster.meta.FtbPersonnlesJobTenureDTO;
import jnpf.model.personnels.dto.roster.meta.FtbPersonnlesJoeInfo;
import jnpf.model.personnels.vo.roster.FtbPersonnlesJobTenureVO;
import jnpf.permission.vo.v2.user.UserBoundVO;
import jnpf.permission.vo.v2.user.UserPageListVO;
import jnpf.personnels.FtbPersonneApi;
import jnpf.personnels.service.FtbPersonnelsMetaDataService;
import jnpf.util.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

@Slf4j
@Service
public class V2CultivateTaskServiceImpl implements V2CultivateTaskService {

    @Autowired
    @Lazy
    private UserApiV2Util userApiV2Util;

    @Autowired
    @Lazy
    private CultivateImUtil cultivateImUtil;

    @Autowired
    @Lazy
    private CultivateLearnTaskIMUtils captchaImUtil;

    @Autowired
    private FtbCultivateLearnTaskService ftbCultivateLearnTaskService;

    @Autowired
    private FtbCultivateLearnTaskAssignmentMapper ftbCultivateLearnTaskAssignmentMapper;


    @Autowired
    private FtbPersonnelsMetaDataService ftbPersonnelsMetaDataService;

    @Autowired
    private FtbCultivateLearnTaskReminderRuleMapper ftbCultivateLearnTaskReminderRuleMapper;


    @Autowired
    private FtbCultivateLearnTaskPhaseMapper ftbCultivateLearnTaskPhaseMapper;


    @Autowired
    private CultivateIdentifyApplyMapper identifyApplyMapper;

    @Autowired
    private CultivateIdentifyApplyDetailsMapper identifyApplyDetailsMapper;

    @Autowired
    private FtbCultivateLearnTaskAssignmentService ftbCultivateLearnTaskAssignmentService;

    @Autowired
    private FtbCultivateLearnTaskPhaseService ftbCultivateLearnTaskPhaseService;

    @Autowired
    private FtbCultivateLearnTaskCourseService ftbCultivateLearnTaskCourseService;

    @Autowired
    private FtbCultivateLearnTaskExamService ftbCultivateLearnTaskExamService;

    @Autowired
    private FtbCultivateLearnTaskIdentificationService ftbCultivateLearnTaskIdentificationService;

    @Autowired
    private FtbCultivateLearnTaskCertificateService ftbCultivateLearnTaskCertificateService;


    @Resource
    private ThreadPoolExecutor cultivateThreadPool;

    @Autowired
    private FtbCultivateTaskLogService ftbCultivateTaskLogService;

    @Autowired
    private FtbCultivateLearnTaskPracticeService ftbCultivateLearnTaskPracticeService;

    @Autowired
    private FtbCultivateLearnTaskMapper ftbCultivateLearnTaskMapper;

    @Autowired
    private V2CultivateBatchQueryService v2CultivateBatchQueryService;

    @Autowired
    private CultivateTaskLeanAsyncDealUtil cultivateTaskLeanAsyncDealUtil;

    @Autowired
    private CultivateCoverInfoMapper cultivateCoverInfoMapper;

    @Autowired
    private FtbCultivateCourseMapper ftbCultivateCourseMapper;

    @Autowired
    private FtbCultivateLearnCategoriesMapper ftbCultivateLearnCategoriesMapper;

    @Autowired
    private CultivateCourseStudyUtil courseStudyUtil;

    @Autowired
    private FtbPersonneApi ftbPersonneApi;

    @Autowired
    private V2CultivateTaskStudyService v2CultivateTaskStudyService;

    /**
     * 根据岗位和司龄筛选用户
     *
     * @param positionIds 岗位 ID 列表（逗号分隔）
     * @param minTenure   最小司龄要求
     * @return 符合条件的用户 ID 列表
     */
    private List<String> filterUsersByPositionAndTenure(String positionIds, Integer minTenure) {
        // 获取岗位下的所有用户
        List<UserBoundVO> userBoundVOList = userApiV2Util.getUserListForPositions(
                List.of(positionIds.split(",")),
                null
        );

        if (CollUtil.isEmpty(userBoundVOList)) {
            return new ArrayList<>();
        }

        // 转换为用户任职信息列表
        List<FtbPersonnlesJoeInfo> joeInfoList = userBoundVOList.stream()
                .map(user -> {
                    FtbPersonnlesJoeInfo info = new FtbPersonnlesJoeInfo();
                    info.setUserId(user.getId());
                    info.setPositionId(user.getPositionId());
                    return info;
                })
                .collect(Collectors.toList());

        // 查询岗龄信息
        FtbPersonnlesJobTenureDTO tenureDTO = new FtbPersonnlesJobTenureDTO();
        tenureDTO.setUserInfo(joeInfoList);
        tenureDTO.setTenantId(UserProvider.getUser().getTenantId());
        String objectToString = JsonUtil.getObjectToString(
                tenureDTO
        );
        log.error("查询岗位司龄信息：{}", objectToString);

        List<FtbPersonnlesJobTenureVO> tenureList = ftbPersonneApi.queryPositionTenureAge(tenureDTO);

        // 筛选满足司龄要求的用户
        if (CollUtil.isEmpty(tenureList)) {
            return new ArrayList<>();
        }

        return tenureList.stream()
                .filter(vo -> vo.getJobTenure() != null && vo.getJobTenure() >= minTenure)
                .map(FtbPersonnlesJobTenureVO::getUserId)
                .collect(Collectors.toList());
    }


    /**
     * 添加学习任务
     *
     * @param req 添加学习任务所需的参数
     * @return 添加成功后的任务ID
     */
    @Override
    @Transactional
    public String add(V2CultivateTaskSaveReq req) {
        //参数校验
        req.beforeCheck();
        v2CultivateBatchQueryService.taskCheckAvailable(req);
        // 任务名称不能重复
        if (queryTaskNumByName(req.getTaskName()) > 0) {
            throw new RuntimeException("任务名称不能重复");
        }
        return realDealTaskData(req);
    }

    /**
     * 学习任务数据
     *
     * @param taskInfoDto 任务信息
     */
    private String realDealTaskData(V2CultivateTaskSaveReq taskInfoDto) {
        // 任务分配规则(1,指定成员,2指定组织,3指定岗位,4自定义)
        List<String> userIds = new ArrayList<>();
        TaskAssignmentRuleEnum taskAssignmentRuleEnum = TaskAssignmentRuleEnum.getByCode(taskInfoDto.getAssignmentRule());
        switch (taskAssignmentRuleEnum) {
            case SPECIFIED_MEMBER:
                // 指定成员
                userIds = taskInfoDto.getUserIds();
                break;
            case SPECIFIED_ORGANIZATION:
                // 指定组织下所有用户
                if (StringUtil.isNotEmpty(taskInfoDto.getAssociationIds())) {
                    List<String> organizeIds = List.of(taskInfoDto.getAssociationIds().split(StringPool.COMMA));
                    List<UserPageListVO> userBaseInfoByOrganizes = userApiV2Util.getUserListForOrgIds(organizeIds, null);
                    if (CollUtil.isNotEmpty(userBaseInfoByOrganizes)) {
                        userIds = userBaseInfoByOrganizes.stream()
                                .map(UserPageListVO::getId)
                                .distinct()
                                .collect(Collectors.toList());
                    }
                }
                break;
            case SPECIFIED_POSITION:
                // 指定岗位下所有用户
                if (StringUtil.isNotEmpty(taskInfoDto.getAssociationIds())) {
                    List<String> positionIds = List.of(taskInfoDto.getAssociationIds().split(StringPool.COMMA));
                    List<UserBoundVO> userBaseInfoByPositions = userApiV2Util.getUserListForPositions(positionIds, null);
                    if (CollUtil.isNotEmpty(userBaseInfoByPositions)) {
                        userIds = userBaseInfoByPositions.stream()
                                .map(UserBoundVO::getId)
                                .distinct()
                                .collect(Collectors.toList());
                    }
                }
                break;
            case CUSTOM:
                // 自定义分配
                if (taskInfoDto.getCustomAssignType() != null) {
                    if (taskInfoDto.getCustomAssignType().equals(0)) {
                        userIds = ftbPersonnelsMetaDataService.queryUserIdsForCompanyAge(
                                taskInfoDto.getStartEntryPeriod(),
                                taskInfoDto.getEndEntryPeriod()
                        );
                    } else if (taskInfoDto.getCustomAssignType().equals(1)
                            && StringUtils.isNotEmpty(taskInfoDto.getCustomAssignPostIds())) {
                        // 根据岗位和司龄筛选用户
                        userIds = filterUsersByPositionAndTenure(
                                taskInfoDto.getCustomAssignPostIds(),
                                taskInfoDto.getEndEntryPeriod()
                        );
                    }
                }
                break;
            default:
                // 默认情况或未知规则，保持 userIds 为空列表
                break;
        }
        //根据封面id查询封面信息
        FtbCultivateCoverInfoEntity coverInfo = cultivateCoverInfoMapper.selectById(taskInfoDto.getCoverId());

        // 任务主表
        FtbCultivateLearnTask ftbCultivateLearnTask = taskInfoDto.convertFtbCultivateLearnTask(taskInfoDto);
        if (coverInfo != null) {
            ftbCultivateLearnTask.setCoverUrl(coverInfo.getPath());
        }

        // 任务展示Id，更新是之前的，新增则为新的
        if (StringUtil.isNotEmpty(taskInfoDto.getId())) {
            FtbCultivateLearnTask oldTaskInfo = ftbCultivateLearnTaskService.getById(ftbCultivateLearnTask.getId());
            if (oldTaskInfo == null || oldTaskInfo.getEnableMark() == 1) {
                throw new RuntimeException("修改任务不存在或已经删除");
            }
            deleteOldTask(taskInfoDto.getId());
            ftbCultivateLearnTask.setId(oldTaskInfo.getId());
            ftbCultivateLearnTask.setLearnTaskShowId(oldTaskInfo.getLearnTaskShowId());
            ftbCultivateLearnTask.setCreatorTime(oldTaskInfo.getCreatorTime());
            ftbCultivateLearnTask.setCreatorUserId(oldTaskInfo.getCreatorUserId());
            ftbCultivateLearnTaskService.updateById(ftbCultivateLearnTask);
        } else {
            ftbCultivateLearnTask.setLearnTaskShowId(SelfGrowthUtil.provideACustomIDBasedOnTheModule(SelfrowingEnum.LEARN_TASK));
            ftbCultivateLearnTaskService.save(ftbCultivateLearnTask);
        }

        // 处理各阶段数据
        List<FtbCultivateLearnTaskCourse> taskCourseList = new ArrayList<>();
        List<FtbCultivateLearnTaskExam> taskExamList = new ArrayList<>();
        List<FtbCultivateLearnTaskIdentification> taskIdentificationList = new ArrayList<>();
        List<FtbCultivateLearnTaskPractice> taskPracticeList = new ArrayList<>();
        List<FtbCultivateLearnTaskCertificate> taskCertificateList = new ArrayList<>();
        List<FtbCultivateLearnTaskPhase> taskPhaseList = new ArrayList<>();

        taskInfoDto.getPhase().forEach(phaseVo -> {
            // 创建阶段
            FtbCultivateLearnTaskPhase phase = new FtbCultivateLearnTaskPhase();
            phase.setId(FtbUtil.getId());
            phase.setTaskId(ftbCultivateLearnTask.getId());
            phase.setQualified(phaseVo.getQualified());
            phase.setCertificateExam(phaseVo.getCertificateExam());
            phase.setCertificateIdentification(phaseVo.getCertificateIdentification());
            phase.setIsPassComplete(phaseVo.getIsPassComplete());
            //设置创建时间 创建人
            phase.setCreatorTime(DateUtil.date());
            phase.setCreatorUserId(UserProvider.getLoginUserId());
            phase.setLastModifyTime(DateUtil.date());
            phase.setLastModifyUserId(UserProvider.getLoginUserId());
            taskPhaseList.add(phase);

            // 处理阶段内的课程
            if (CollUtil.isNotEmpty(phaseVo.getCourseList())) {
                phaseVo.getCourseList().forEach(courseInfo -> {
                    FtbCultivateLearnTaskCourse course = new FtbCultivateLearnTaskCourse();
                    course.setTaskId(ftbCultivateLearnTask.getId());
                    course.setCourseId(courseInfo.getCourseId());
                    course.setIsRequired(courseInfo.getIsRequired());
                    course.setPhaseId(phase.getId()); // 关联阶段ID

                    course.setCreatorTime(DateUtil.date());
                    course.setCreatorUserId(UserProvider.getLoginUserId());
                    course.setLastModifyTime(DateUtil.date());
                    course.setLastModifyUserId(UserProvider.getLoginUserId());
                    taskCourseList.add(course);
                });
            }

            // 处理阶段内的考试
            if (phaseVo.getExam() != null) {
                FtbCultivateLearnTaskExam exam = new FtbCultivateLearnTaskExam();
                exam.setTaskId(ftbCultivateLearnTask.getId());
                exam.setExamId(phaseVo.getExam().getExamId());
                exam.setPhaseId(phase.getId()); // 关联阶段ID
                exam.setCreatorTime(DateUtil.date());
                exam.setCreatorUserId(UserProvider.getLoginUserId());
                exam.setLastModifyTime(DateUtil.date());
                exam.setLastModifyUserId(UserProvider.getLoginUserId());
                taskExamList.add(exam);
            }

            // 处理阶段内的鉴定
            if (phaseVo.getIdentification() != null && phaseVo.getIdentification() != null) {
                FtbCultivateLearnTaskIdentification identification = new FtbCultivateLearnTaskIdentification();
                identification.setTaskId(ftbCultivateLearnTask.getId());
                identification.setIdentificationId(phaseVo.getIdentification().getIdentityId());
                identification.setPhaseId(phase.getId()); // 关联阶段ID
                identification.setCreatorTime(DateUtil.date());
                identification.setCreatorUserId(UserProvider.getLoginUserId());
                identification.setLastModifyTime(DateUtil.date());
                identification.setLastModifyUserId(UserProvider.getLoginUserId());
                taskIdentificationList.add(identification);
            }

            // 处理阶段内的练习
            if (CollUtil.isNotEmpty(phaseVo.getPracticeList())) {
                phaseVo.getPracticeList().forEach(practiceInfo -> {
                    FtbCultivateLearnTaskPractice practice = new FtbCultivateLearnTaskPractice();
                    practice.setTaskId(ftbCultivateLearnTask.getId());
                    practice.setBusinessId(practiceInfo.getBusinessId());
                    practice.setNum(practiceInfo.getNum());
                    practice.setPhaseId(phase.getId()); // 关联阶段ID
                    practice.setCreatorTime(DateUtil.date());
                    practice.setCreatorUserId(UserProvider.getLoginUserId());
                    practice.setLastModifyTime(DateUtil.date());
                    practice.setLastModifyUserId(UserProvider.getLoginUserId());
                    taskPracticeList.add(practice);
                });
            }

            // 处理阶段内的证书
            if (phaseVo.getCertificateIdentification() != null && phaseVo.getCertificate() != null) {
                FtbCultivateLearnTaskCertificate certificate = new FtbCultivateLearnTaskCertificate();
                certificate.setTaskId(ftbCultivateLearnTask.getId());
                certificate.setCertificateId(phaseVo.getCertificate().getCertificateId());
                certificate.setPhaseId(phase.getId()); // 关联阶段ID
                certificate.setCreatorTime(DateUtil.date());
                certificate.setCreatorUserId(UserProvider.getLoginUserId());
                certificate.setLastModifyTime(DateUtil.date());
                certificate.setLastModifyUserId(UserProvider.getLoginUserId());
                taskCertificateList.add(certificate);
            }
        });

        // 批量插入各阶段数据
        if (CollUtil.isNotEmpty(taskPhaseList)) {
            ftbCultivateLearnTaskPhaseService.saveBatch(taskPhaseList);
        }

        if (CollUtil.isNotEmpty(taskCourseList)) {
            ftbCultivateLearnTaskCourseService.saveBatch(taskCourseList);
        }

        if (CollUtil.isNotEmpty(taskExamList)) {
            ftbCultivateLearnTaskExamService.saveBatch(taskExamList);
        }

        if (CollUtil.isNotEmpty(taskIdentificationList)) {
            ftbCultivateLearnTaskIdentificationService.saveBatch(taskIdentificationList);
        }

        if (CollUtil.isNotEmpty(taskPracticeList)) {
            ftbCultivateLearnTaskPracticeService.saveBatch(taskPracticeList);
        }

        if (CollUtil.isNotEmpty(taskCertificateList)) {
            ftbCultivateLearnTaskCertificateService.saveBatch(taskCertificateList);
        }

        // 任务学习关联规则提醒
        FtbCultivateLearnTaskReminderRule ftbCultivateLearnTaskReminderRule = taskInfoDto.convertTaskReminderRule(taskInfoDto);
        ftbCultivateLearnTaskReminderRule.setTaskId(ftbCultivateLearnTask.getId());
        ftbCultivateLearnTaskReminderRuleMapper.insert(ftbCultivateLearnTaskReminderRule);
        // 学习任务关联人
        List<FtbCultivateLearnTaskAssignment> ftbCultivateLearnTaskAssignments = userIds.stream().map(a -> {
            FtbCultivateLearnTaskAssignment ftbCultivateLearnTaskAssignment = new FtbCultivateLearnTaskAssignment();
            ftbCultivateLearnTaskAssignment.setTaskId(ftbCultivateLearnTask.getId());
            ftbCultivateLearnTaskAssignment.setStudyStats(0);
            ftbCultivateLearnTaskAssignment.setUserId(a);
            return ftbCultivateLearnTaskAssignment;
        }).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(ftbCultivateLearnTaskAssignments)) {
            ftbCultivateLearnTaskAssignmentService.saveBatch(ftbCultivateLearnTaskAssignments);
        }


        // 任务进行中，启用提醒后，任务开始时将提醒员工
        if (ftbCultivateLearnTask.getStatus() == 2
                && ftbCultivateLearnTaskReminderRule.getTaskStartReminder() == 1
                && CollUtil.isNotEmpty(userIds)) {
            List<NeedAlertUserDto> alertUserList = userIds.stream().map(a -> {
                NeedAlertUserDto needAlertUserDto = new NeedAlertUserDto();
                needAlertUserDto.setUserId(a);
                needAlertUserDto.setTaskId(ftbCultivateLearnTask.getId());
                needAlertUserDto.setTaskName(ftbCultivateLearnTask.getTaskName());
                return needAlertUserDto;
            }).collect(Collectors.toList());
            String tenantId = UserProvider.getUser().getTenantId();
            CompletableFuture.runAsync(() -> {
                captchaImUtil.sendMsg(alertUserList, tenantId);
            }, cultivateThreadPool);
        }
        if (ftbCultivateLearnTask.getStatus().equals(2)) {
            List<String> courseIds = taskCourseList.stream().map(FtbCultivateLearnTaskCourse::getCourseId).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(courseIds) && CollUtil.isNotEmpty(userIds)) {
                userIds = UserApiV2Util.uniqueStringList(userIds);
                courseIds = UserApiV2Util.uniqueStringList(courseIds);
                courseStudyUtil.batchInitCourseStudyRecord(userIds, courseIds, UserProvider.getUser().getTenantId());
            }
        }

        return ftbCultivateLearnTask.getId();
    }


    public void deleteOldTask(String id) {
        // 任务删除
        LambdaUpdateWrapper<FtbCultivateLearnTask> deleteLearnTaskWrapper = Wrappers.lambdaUpdate();
        deleteLearnTaskWrapper.eq(SuperBaseEntity.SuperIBaseEntity::getId, id);
        deleteLearnTaskWrapper.set(FtbCultivateLearnTask::getEnableMark, 1); // 逻辑删除
        ftbCultivateLearnTaskService.update(deleteLearnTaskWrapper);
        // 任务人员
        LambdaUpdateWrapper<FtbCultivateLearnTaskAssignment> deleteLearnTaskAssignmentWrapper = Wrappers.lambdaUpdate();
        deleteLearnTaskAssignmentWrapper.eq(FtbCultivateLearnTaskAssignment::getTaskId, id);
        ftbCultivateLearnTaskAssignmentService.remove(deleteLearnTaskAssignmentWrapper);
        // 任务课程
        LambdaUpdateWrapper<FtbCultivateLearnTaskCourse> deleteCourseWrapper = Wrappers.lambdaUpdate();
        deleteCourseWrapper.eq(FtbCultivateLearnTaskCourse::getTaskId, id);
        ftbCultivateLearnTaskCourseService.remove(deleteCourseWrapper);
        // 任务考试
        LambdaUpdateWrapper<FtbCultivateLearnTaskExam> deleteExamWrapper = Wrappers.lambdaUpdate();
        deleteExamWrapper.eq(FtbCultivateLearnTaskExam::getTaskId, id);
        ftbCultivateLearnTaskExamService.remove(deleteExamWrapper);
        // 任务鉴定
        LambdaUpdateWrapper<FtbCultivateLearnTaskIdentification> deleteIdentificationWrapper = Wrappers.lambdaUpdate();
        deleteIdentificationWrapper.eq(FtbCultivateLearnTaskIdentification::getTaskId, id);
        ftbCultivateLearnTaskIdentificationService.remove(deleteIdentificationWrapper);

        // 任务证书
        LambdaUpdateWrapper<FtbCultivateLearnTaskCertificate> deleteCertificateWrapper = Wrappers.lambdaUpdate();
        deleteCertificateWrapper.eq(FtbCultivateLearnTaskCertificate::getTaskId, id);
        ftbCultivateLearnTaskCertificateService.remove(deleteCertificateWrapper);

        // 练习
        LambdaUpdateWrapper<FtbCultivateLearnTaskPractice> practiceWrapper = Wrappers.lambdaUpdate();
        practiceWrapper.eq(FtbCultivateLearnTaskPractice::getTaskId, id);
        ftbCultivateLearnTaskPracticeService.remove(practiceWrapper);

        //阶段
        LambdaUpdateWrapper<FtbCultivateLearnTaskPhase> phaseWrapper = Wrappers.lambdaUpdate();
        phaseWrapper.eq(FtbCultivateLearnTaskPhase::getTaskId, id);
        ftbCultivateLearnTaskPhaseService.remove(phaseWrapper);

        // 任务提醒鉴定
        LambdaUpdateWrapper<FtbCultivateLearnTaskReminderRule> deleteReminderWrapper = Wrappers.lambdaUpdate();
        deleteReminderWrapper.eq(FtbCultivateLearnTaskReminderRule::getTaskId, id);
        deleteReminderWrapper.eq(FtbCultivateLearnTaskReminderRule::getEnableMark, 0);
        ftbCultivateLearnTaskReminderRuleMapper.delete(deleteReminderWrapper);

        //删除任务阶段学习
        LambdaQueryWrapper<FtbCultivateTaskLog> taskLogWrapper = Wrappers.lambdaQuery();
        taskLogWrapper.eq(FtbCultivateTaskLog::getTaskId, id);
        ftbCultivateTaskLogService.remove(taskLogWrapper);

        // 删除任务未完成的鉴定
        LambdaQueryWrapper<CultivateIdentifyApply> identifyApplyLambdaQueryWrapper = Wrappers.lambdaQuery();
        identifyApplyLambdaQueryWrapper.select(CultivateIdentifyApply::getId);
        identifyApplyLambdaQueryWrapper.eq(CultivateIdentifyApply::getSourceId, id);
        identifyApplyLambdaQueryWrapper.eq(CultivateIdentifyApply::getSource, 4);
        List<CultivateIdentifyApply> cultivateIdentifyAppliesList = identifyApplyMapper.selectList(identifyApplyLambdaQueryWrapper);
        if (CollUtil.isNotEmpty(cultivateIdentifyAppliesList)) {
            List<String> identifyApplyIds = cultivateIdentifyAppliesList.stream().map(SuperBaseEntity.SuperIBaseEntity::getId).collect(Collectors.toList());
            identifyApplyMapper.deleteBatchIds(identifyApplyIds);

            LambdaQueryWrapper<CultivateIdentifyApplyDetails> deleteApplyDetailsWrapper = Wrappers.lambdaQuery();
            deleteApplyDetailsWrapper.in(CultivateIdentifyApplyDetails::getApplyId, identifyApplyIds);
            identifyApplyDetailsMapper.delete(deleteApplyDetailsWrapper);
        }

        // 删除任务关联考试
        //todo v2 怎么删除考试
    }


    /**
     * 修改学习任务
     *
     * @param req 修改学习任务所需的参数
     * @return 修改成功后的任务ID
     */
    @Override
    @Transactional
    public String update(V2CultivateTaskSaveReq req) {

        req.beforeCheck();
        FtbCultivateLearnTask repeatNameTask = queryTaskInfoByName(req.getTaskName());
        if (repeatNameTask != null && !repeatNameTask.getId().equals(req.getId())) {
            throw new RuntimeException("任务名称重复");
        }
        return realDealTaskData(req);
    }

    /**
     * 分配任务(给用户分配任务)
     *
     * @param req 分配数据传输对象，包含分配培养学习所需的各项数据
     */
    @Override
    public void allocation(FtbCultivateLearnAllocationDTO req) {
        FtbCultivateLearnTask entity = ftbCultivateLearnTaskService.getById(req.getTaskId());
        if (entity == null || entity.getEnableMark() == 1) {
            throw new RuntimeException("任务不存在");
        }
        LambdaQueryWrapper<FtbCultivateLearnTaskAssignment> taskAssignmentLambdaQueryWrapper = Wrappers.lambdaQuery();
        taskAssignmentLambdaQueryWrapper.select(FtbCultivateLearnTaskAssignment::getUserId);
        taskAssignmentLambdaQueryWrapper.eq(FtbCultivateLearnTaskAssignment::getTaskId, req.getTaskId());
        taskAssignmentLambdaQueryWrapper.eq(FtbCultivateLearnTaskAssignment::getEnableMark, 0);
        List<FtbCultivateLearnTaskAssignment> oldLearnTaskAssignments = ftbCultivateLearnTaskAssignmentService.list(taskAssignmentLambdaQueryWrapper);
        List<String> oldUserIds = oldLearnTaskAssignments.stream()
                .map(FtbCultivateLearnTaskAssignment::getUserId)
                .collect(Collectors.toList());

        // 计算需要移除的用户ID（在旧列表中但不在新列表中的用户）
        List<String> removeUserIds = oldUserIds.stream()
                .filter(userId -> !req.getUserIds().contains(userId))
                .collect(Collectors.toList());
        if (CollUtil.isNotEmpty(removeUserIds)) {
            // 移除不在新列表中的用户
            LambdaQueryWrapper<FtbCultivateLearnTaskAssignment> removeWrapper = Wrappers.lambdaQuery();
            removeWrapper.eq(FtbCultivateLearnTaskAssignment::getTaskId, req.getTaskId());
            removeWrapper.in(FtbCultivateLearnTaskAssignment::getUserId, removeUserIds);
            ftbCultivateLearnTaskAssignmentService.remove(removeWrapper);
        }

        // 计算需要新增的用户ID
        List<String> newAddedUserIds = req.getUserIds()
                .stream()
                .filter(userId -> !oldUserIds.contains(userId))
                .collect(Collectors.toList());
        if (CollUtil.isNotEmpty(newAddedUserIds)) {
            // 新人员绑定
            List<FtbCultivateLearnTaskAssignment> ftbCultivateLearnTaskAssignments = newAddedUserIds.stream().map(a -> {
                FtbCultivateLearnTaskAssignment ftbCultivateLearnTaskAssignment = new FtbCultivateLearnTaskAssignment();
                ftbCultivateLearnTaskAssignment.setTaskId(req.getTaskId());
                ftbCultivateLearnTaskAssignment.setUserId(a);
                ftbCultivateLearnTaskAssignment.setStudyStats(0);
                return ftbCultivateLearnTaskAssignment;
            }).collect(Collectors.toList());
            ftbCultivateLearnTaskAssignmentService.saveBatch(ftbCultivateLearnTaskAssignments);
        }

    }

    /**
     * 中止指定任务
     *
     * @param taskId 任务ID，用于标识需要中止的任务
     */
    @Override
    public void abort(String taskId) {
        FtbCultivateLearnTask entity = ftbCultivateLearnTaskService.getById(taskId);
        if (entity == null || entity.getEnableMark() == 1) {
            throw new RuntimeException("任务不存在");
        }

        // 任务中止
        LambdaUpdateWrapper<FtbCultivateLearnTask> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.eq(FtbCultivateLearnTask::getId, taskId);
        updateWrapper.set(FtbCultivateLearnTask::getStatus, 4);
        ftbCultivateLearnTaskService.update(new FtbCultivateLearnTask(), updateWrapper);
        List<String> userIds = queryUserListForTaskNoComplete(taskId);
        //终止用户

//        LambdaUpdateWrapper<FtbCultivateLearnTaskAssignment> assignUpdateWrapper = Wrappers.lambdaUpdate();
//        assignUpdateWrapper.eq(FtbCultivateLearnTaskAssignment::getTaskId, taskId)
//                .ne(FtbCultivateLearnTaskAssignment::getStudyStats, 2)
//                .eq(FtbCultivateLearnTaskAssignment::getEnableMark, 0)
//                .set(FtbCultivateLearnTaskAssignment::getStudyStats, 4);
//        ftbCultivateLearnTaskAssignmentService.update(assignUpdateWrapper);

        if (CollUtil.isNotEmpty(userIds)) {
            String tenantId = UserProvider.getUser().getTenantId();
            String pushMessageContent = "您的任务【" + entity.getTaskName() + "】已终止，无法继续进行任务！";
            cultivateImUtil.sendTaskAbortMessage(userIds, tenantId, pushMessageContent);
        }
    }

    /**
     * 查询未完成的学员
     *
     * @param taskId 任务id
     * @return
     */
    public List<String> queryUserListForTaskNoComplete(String taskId) {
        LambdaQueryWrapper<FtbCultivateLearnTaskAssignment> assignmentQueryWrapper = Wrappers.lambdaQuery();
        assignmentQueryWrapper.eq(FtbCultivateLearnTaskAssignment::getTaskId, taskId);
        assignmentQueryWrapper.ne(FtbCultivateLearnTaskAssignment::getStudyStats, 2);
        assignmentQueryWrapper.eq(FtbCultivateLearnTaskAssignment::getEnableMark, 0);
        List<FtbCultivateLearnTaskAssignment> list = ftbCultivateLearnTaskAssignmentService.list(assignmentQueryWrapper);
        if (CollUtil.isNotEmpty(list)) {
            return list.stream().map(FtbCultivateLearnTaskAssignment::getUserId).collect(Collectors.toList());
        }
        return CollUtil.newArrayList();
    }

    /**
     * 删除指定ID的任务
     *
     * @param id 任务的唯一标识符
     */
    @Override
    @Transactional
    public void deleteTask(String id) {
        deleteOldTask(id);
    }


    /**
     * 获取指定ID的任务详情
     *
     * @param id 任务ID
     * @return 任务详情
     */
    @Override
    public V2CultivateTaskDetailsVo get(String id) {
        // 查询任务主表
        FtbCultivateLearnTask task = ftbCultivateLearnTaskService.getById(id);
        if (task == null) {
            return null;
        }

        // 构建返回对象
        V2CultivateTaskDetailsVo vo = new V2CultivateTaskDetailsVo();
        vo.convert(task);
        if (StringUtils.isNotEmpty(task.getTaskClass())) {
            FtbCultivateLearnCategories categories = ftbCultivateLearnCategoriesMapper.selectById(task.getTaskClass());
            if (categories != null) {
                vo.setTaskClassName(categories.getName());
            }
        }

        // 批量查询任务关联的所有数据
        // 查询任务阶段表
        LambdaQueryWrapper<FtbCultivateLearnTaskPhase> phaseWrapper = Wrappers.lambdaQuery();
        phaseWrapper.eq(FtbCultivateLearnTaskPhase::getTaskId, id);
        phaseWrapper.eq(FtbCultivateLearnTaskPhase::getEnableMark, 0); // 只查询有效的
        List<FtbCultivateLearnTaskPhase> phaseList = ftbCultivateLearnTaskPhaseService.list(phaseWrapper);

        // 如果没有阶段，则直接返回
        if (CollUtil.isEmpty(phaseList)) {
            vo.setPhase(new ArrayList<>());
            return vo;
        }

        // 批量查询所有阶段的课程、考试、鉴定、证书和练习 - 使用新封装的方法
        List<FtbCultivateLearnTaskCourseVo> courseEntities = ftbCultivateLearnTaskCourseService.listByTaskId(id, null);
        List<FtbCultivateLearnTaskExamVo> examEntities = ftbCultivateLearnTaskExamService.listByTaskId(id);
        List<FtbCultivateLearnTaskIdentificationVo> identificationEntities = ftbCultivateLearnTaskIdentificationService.listByTaskId(id);
        List<FtbCultivateLearnTaskCertificateVo> certificateEntities = ftbCultivateLearnTaskCertificateService.listByTaskId(id);
        List<FtbCultivateLearnTaskPracticeVo> practiceEntities = ftbCultivateLearnTaskPracticeService.listByTaskId(id);

        // 按阶段分组数据
        Map<String, List<FtbCultivateLearnTaskCourseVo>> courseGroupByPhase = courseEntities.stream()
                .collect(Collectors.groupingBy(FtbCultivateLearnTaskCourseVo::getPhaseId));
        Map<String, List<FtbCultivateLearnTaskExamVo>> examGroupByPhase = examEntities.stream()
                .collect(Collectors.groupingBy(FtbCultivateLearnTaskExamVo::getPhaseId));
        Map<String, List<FtbCultivateLearnTaskIdentificationVo>> identificationGroupByPhase = identificationEntities.stream()
                .collect(Collectors.groupingBy(FtbCultivateLearnTaskIdentificationVo::getPhaseId));
        Map<String, List<FtbCultivateLearnTaskCertificateVo>> certificateGroupByPhase = certificateEntities.stream()
                .collect(Collectors.groupingBy(FtbCultivateLearnTaskCertificateVo::getPhaseId));
        Map<String, List<FtbCultivateLearnTaskPracticeVo>> practiceGroupByPhase = practiceEntities.stream()
                .collect(Collectors.groupingBy(FtbCultivateLearnTaskPracticeVo::getPhaseId));

        // 按照阶段分组并组装数据
        List<V2CultivateLearnTaskPhaseVo> phaseVoList = new ArrayList<>();
        for (FtbCultivateLearnTaskPhase phase : phaseList) {
            V2CultivateLearnTaskPhaseVo phaseVo = new V2CultivateLearnTaskPhaseVo();
            phaseVo.convert(phase);
            String phaseId = phase.getId();
            // 处理课程列表 - 按照sortCode升序排序
            List<FtbCultivateLearnTaskCourseVo> courseInPhase = courseGroupByPhase.getOrDefault(phaseId, new ArrayList<>());
            // 按排序字段升序排列
            courseInPhase.sort((a, b) -> {
                Integer sortA = a.getSortCode() != null ? a.getSortCode() : 0;
                Integer sortB = b.getSortCode() != null ? b.getSortCode() : 0;
                return sortA.compareTo(sortB);
            });

            List<V2CultivateLearnTaskCourseVo> courseList = new ArrayList<>();
            for (FtbCultivateLearnTaskCourseVo course : courseInPhase) {
                // 设置课程名称
                V2CultivateLearnTaskCourseVo courseVo = new V2CultivateLearnTaskCourseVo();
                courseVo.convert(course);
                courseVo.setCourseName(course.getCourseName());
                courseVo.setBusinessSource(PositionBusinessSourceEnum.TASK_LEARNING);
                courseVo.setBusinessSourceId(task.getId());
                courseList.add(courseVo);
            }
            phaseVo.setCourseList(courseList);

            // 处理考试信息
            List<FtbCultivateLearnTaskExamVo> examInPhase = examGroupByPhase.getOrDefault(phaseId, new ArrayList<>());
            if (CollUtil.isNotEmpty(examInPhase)) {
                FtbCultivateLearnTaskExamVo examEntity = examInPhase.get(0); // 每个阶段最多一个考试
                // 设置考试名称
                V2CultivateLearnTaskExamVo examVo = new V2CultivateLearnTaskExamVo();
                examVo.convert(examEntity);
                examVo.setExamName(examEntity.getExamName());
                phaseVo.setExam(examVo);

            }

            // 处理鉴定信息
            List<FtbCultivateLearnTaskIdentificationVo> identificationInPhase = identificationGroupByPhase.getOrDefault(phaseId, new ArrayList<>());
            if (CollUtil.isNotEmpty(identificationInPhase)) {
                FtbCultivateLearnTaskIdentificationVo identificationEntity = identificationInPhase.get(0); // 每个阶段最多一个鉴定
                V2CultivateLearnTaskIdentificationVo identificationVo = new V2CultivateLearnTaskIdentificationVo();
                identificationVo.convert(identificationEntity);
                identificationVo.setIdentityName(identificationEntity.getIdentificationName()); // 使用identityId作为名称，可能需要根据实际需求调整
                identificationVo.setBusinessSource(PositionBusinessSourceEnum.TASK_LEARNING);
                identificationVo.setBusinessSourceId(task.getId());
                phaseVo.setIdentification(identificationVo);
            }

            // 处理证书信息
            List<FtbCultivateLearnTaskCertificateVo> certificateInPhase = certificateGroupByPhase.getOrDefault(phaseId, new ArrayList<>());
            if (CollUtil.isNotEmpty(certificateInPhase)) {
                FtbCultivateLearnTaskCertificateVo certificateEntity = certificateInPhase.get(0); // 每个阶段最多一个证书

                V2CultivateLearnTaskCertificateVo certificateVo = new V2CultivateLearnTaskCertificateVo();
                certificateVo.convert(certificateEntity);
                certificateVo.setCertificateName(certificateEntity.getCertName());
                phaseVo.setCertificate(certificateVo);
            }

            // 处理练习列表
            List<FtbCultivateLearnTaskPracticeVo> practiceInPhase = practiceGroupByPhase.getOrDefault(phaseId, new ArrayList<>());

            List<V2CultivateLearnTaskPracticeVo> practiceList = new ArrayList<>();
            for (FtbCultivateLearnTaskPracticeVo practice : practiceInPhase) {
                // 设置技能名称，从教学技能映射中获取
                V2CultivateLearnTaskPracticeVo practiceVo = new V2CultivateLearnTaskPracticeVo();
                practiceVo.convert(practice);
                practiceVo.setBusinessName(practice.getBusinessName());
                practiceVo.setCompleteNum(0); // 暂时设为0，需要根据实际情况查询
                practiceVo.setStatus(0); // 暂时设为0，需要根据实际情况查询
                practiceList.add(practiceVo);
            }
            phaseVo.setPracticeList(practiceList);
            phaseVoList.add(phaseVo);
        }
        vo.setPhase(phaseVoList);

        // 查询任务提醒规则
        LambdaQueryWrapper<FtbCultivateLearnTaskReminderRule> reminderRuleWrapper = Wrappers.lambdaQuery();
        reminderRuleWrapper.eq(FtbCultivateLearnTaskReminderRule::getTaskId, id)
                .eq(FtbCultivateLearnTaskReminderRule::getEnableMark, 0); // 只查询有效的
        FtbCultivateLearnTaskReminderRule reminderRule = ftbCultivateLearnTaskReminderRuleMapper.selectOne(reminderRuleWrapper);

        if (reminderRule != null) {
            vo.setTaskStartReminder(reminderRule.getTaskStartReminder());
            vo.setTaskEndReminder(reminderRule.getTaskEndReminder());
            vo.setPerInterval(reminderRule.getPerInterval());
        }

        return vo;
    }

    /**
     * App查询任务列表
     * <p>
     * vo.setTaskStartReminder(reminderRule.getTaskStartReminder());
     * vo.setTaskEndReminder(reminderRule.getTaskEndReminder());
     * vo.setPerInterval(reminderRule.getPerInterval());
     * }
     * <p>
     * return vo;
     * }
     * <p>
     * /**
     * App查询任务列表
     *
     * @param taskListDto 查询任务列表所需的参数
     * @return 任务列表
     */
    @Override
    public PageListVO<V2CultivateTaskListForManagerVo> queryTaskListForApp(V2CultivateLearnTaskListForManagerReq taskListDto) {
        Page<V2CultivateTaskListForManagerVo> page = taskListDto.coverCultivatePage();
        page = ftbCultivateLearnTaskMapper.queryTaskListForApp(
                page,
                taskListDto.getKeyWords(),
                taskListDto.getStatus()
        );
        List<V2CultivateTaskListForManagerVo> records = page.getRecords();
        if (CollUtil.isNotEmpty(records)) {
            //获取任务IDs
            List<String> taskIds = records.stream().map(V2CultivateTaskListForManagerVo::getId).collect(Collectors.toList());
            // 查询任务的总人数 map<taskId,Long>
            List<BatchCommonCountDto> totalCountList = ftbCultivateLearnTaskAssignmentMapper.groupCountNum(taskIds, 0);
            Map<String, Long> totalNumMap = totalCountList.stream()
                    .collect(Collectors.toMap(BatchCommonCountDto::getSelectKey, item -> item.getNum().longValue()));

            // 查询任务的完成人数 map<taskId,Long>
            List<BatchCommonCountDto> completeCountList = ftbCultivateLearnTaskAssignmentMapper.groupCountNum(taskIds, 1);
            Map<String, Long> completeNumMap = completeCountList.stream()
                    .collect(Collectors.toMap(BatchCommonCountDto::getSelectKey, item -> item.getNum().longValue()));

            // 查询任务的阶段数 map<taskId,Long>
            List<BatchCommonCountDto> phaseCountList = ftbCultivateLearnTaskPhaseMapper.groupCountNum(taskIds);
            Map<String, Long> phaseNumMap = phaseCountList.stream()
                    .collect(Collectors.toMap(BatchCommonCountDto::getSelectKey, item -> item.getNum().longValue()));
            // 目前使用现有字段taskNumber, taskCompleteNumber, phaseNum
            for (V2CultivateTaskListForManagerVo record : records) {
                record.setTaskNumber(Math.toIntExact(totalNumMap.getOrDefault(record.getId(), 0L)));
                record.setTaskCompleteNumber(Math.toIntExact(completeNumMap.getOrDefault(record.getId(), 0L)));
                record.setPhaseNum(phaseNumMap.getOrDefault(record.getId(), 0L));
            }
        }

        return CultivatePage.coverPageList(page);
    }

    /**
     * App查询任务数量
     *
     * @param keyWord 关键字
     * @return 任务数量
     */
    @Override
    public Map<String, Integer> queryTaskCountForApp(String keyWord) {
        // 查询各个状态的任务数量，添加空值检查
        Long count1 = ftbCultivateLearnTaskMapper.queryTaskCountForApp(keyWord, LearnTaskStatusEnum.NOT_STARTED.getCode());
        Long count2 = ftbCultivateLearnTaskMapper.queryTaskCountForApp(keyWord, LearnTaskStatusEnum.IN_PROGRESS.getCode());
        Long count3 = ftbCultivateLearnTaskMapper.queryTaskCountForApp(keyWord, LearnTaskStatusEnum.FINISHED.getCode());

        // 对可能为null的值进行安全转换
        return Map.of(
                "noStart", count1 != null ? count1.intValue() : 0,
                "doing", count2 != null ? count2.intValue() : 0,
                "over", count3 != null ? count3.intValue() : 0
        );
    }

    /**
     * App查询任务完成统计
     *
     * @param taskId 任务ID
     * @return 任务完成统计
     */
    @Override
    public V2CultivateLearnTaskFinishStatisticsVo getCompletionStatisticsForManagerApp(String taskId) {
        // 参数验证
        if (taskId == null) {
            return new V2CultivateLearnTaskFinishStatisticsVo();
        }

        // 根据任务统计该任务下人员完成情况
        V2CultivateLearnTaskFinishStatisticsVo statisticsVO = new V2CultivateLearnTaskFinishStatisticsVo();
        LambdaQueryWrapper<FtbCultivateLearnTaskAssignment> taskAssignmentLambdaQueryWrapper = Wrappers.lambdaQuery();
        taskAssignmentLambdaQueryWrapper.select(FtbCultivateLearnTaskAssignment::getUserId,
                FtbCultivateLearnTaskAssignment::getStudyStats);
        taskAssignmentLambdaQueryWrapper.eq(FtbCultivateLearnTaskAssignment::getTaskId, taskId);
        taskAssignmentLambdaQueryWrapper.eq(FtbCultivateLearnTaskAssignment::getEnableMark, 0);
        List<FtbCultivateLearnTaskAssignment> taskAssignmentList = ftbCultivateLearnTaskAssignmentMapper.selectList(taskAssignmentLambdaQueryWrapper);
        Map<Integer, List<FtbCultivateLearnTaskAssignment>> listMap = taskAssignmentList.stream().collect(Collectors.groupingBy(FtbCultivateLearnTaskAssignment::getStudyStats, Collectors.toList()));
        // 应完成人数
        // 0未开始，1进行中，2已完成，3已逾期
        statisticsVO.setBeComplete(taskAssignmentList.size());
        // 0未开始
        statisticsVO.setNoStart(listMap.getOrDefault(0, Collections.emptyList()).size());
        // 1进行中
        statisticsVO.setDoing(listMap.getOrDefault(1, Collections.emptyList()).size());
        // 2已完成
        statisticsVO.setComplete(listMap.getOrDefault(2, Collections.emptyList()).size());
        // 3已逾期
        statisticsVO.setOverdue(listMap.getOrDefault(3, Collections.emptyList()).size());
        return statisticsVO;
    }

    /**
     * App查询任务完成情况用户列表
     *
     * @param taskId 课程ID
     * @param page   分页参数
     * @return 任务完成用户列表
     */
    @Override
    public PageListVO<V2CultivateTaskFinishUserListVo> queryTaskUserListForManagerApp(String taskId, CultivatePage page) {
        Page<V2CultivateTaskFinishUserListVo> searchPage = page.coverCultivatePage();
        searchPage = ftbCultivateLearnTaskAssignmentMapper.queryTaskUserListForManagerApp(searchPage, taskId);
        List<V2CultivateTaskFinishUserListVo> records = searchPage.getRecords();
        if (CollUtil.isNotEmpty(records)) {
            List<String> userIds = records.stream().map(V2CultivateTaskFinishUserListVo::getUserId).collect(Collectors.toList());
            Map<String, UserBoundVO> userBoundVOMap = userApiV2Util.getUserPrimaryBoundBatch(userIds, null);
            records.forEach(item -> {
                UserBoundVO userBoundVO = userBoundVOMap.get(item.getUserId());
                if (userBoundVO != null) {
                    item.setUserName(userBoundVO.getUserName());
                    item.setOrgName(userBoundVO.getOrganizeName());
                    item.setPostName(userBoundVO.getPositionName());
                    item.setGradeName(userBoundVO.getGradeName());
                    item.setEmployeeID(userBoundVO.getSystemWorkerId());
                }

                if (item.getTaskStartTime() != null && item.getTaskEndTime() != null) {
                    // 计算任务时长
                    TimeDifference timeDifference = CultivateDateTimeUtils.calculateDifference(item.getTaskStartTime(), item.getTaskEndTime());
                    item.setTaskDuration(timeDifference.toString());
                }
            });
        }
        return CultivatePage.coverPageList(searchPage);
    }


    /**
     * App查询我的任务列表
     *
     * @param taskListDto 查询任务列表所需的参数
     * @return 我的任务列表
     */
    @Override
    public PageListVO<V2MyCultivateLearnTaskListVo> queryMyTaskListForApp(V2MyCultivateTaskListForReq taskListDto) {
        String userId = UserProvider.getUser().getUserId();

        Page<V2MyCultivateLearnTaskListVo> tPage = taskListDto.coverCultivatePage();
        Page<V2MyCultivateLearnTaskListVo> taskPage = ftbCultivateLearnTaskMapper.queryMyTaskListForApp(tPage, taskListDto, userId);
        if (CollUtil.isNotEmpty(taskPage.getRecords())) {
            List<String> taskIds = new ArrayList<>();
            taskPage.getRecords().forEach(item -> {
                if (item.getTaskType() == 1) {
                    Date learningEndTime = item.getTimeLimitEndTime();
                    String remainingValue = CultivateDateTimeUtils.calculateRemainingValue(new Date(), learningEndTime, 0);
                    item.setDaysRemaining(remainingValue);
                }
                taskIds.add(item.getTaskId());
            });

            LambdaQueryWrapper<FtbCultivateLearnTaskPhase> phaseWrapper = Wrappers.lambdaQuery();
            phaseWrapper.in(FtbCultivateLearnTaskPhase::getTaskId, taskIds);
            phaseWrapper.eq(FtbCultivateLearnTaskPhase::getEnableMark, 0); // 只查询有效的
            phaseWrapper.orderByAsc(FtbCultivateLearnTaskPhase::getCreatorTime);
            List<FtbCultivateLearnTaskPhase> phaseList = ftbCultivateLearnTaskPhaseService.list(phaseWrapper);
            //按照任务id分组
            Map<String, List<FtbCultivateLearnTaskPhase>> phaseMap = phaseList.stream().collect(Collectors.groupingBy(FtbCultivateLearnTaskPhase::getTaskId));
            List<FtbCultivateTaskLog> completePhaseList = ftbCultivateTaskLogService.batchQueryCompleteTaskPhase(taskIds, userId);
            Map<String, List<FtbCultivateTaskLog>> completePhaseMap = completePhaseList.stream().collect(Collectors.groupingBy(FtbCultivateTaskLog::getTaskId));
            for (V2MyCultivateLearnTaskListVo record : taskPage.getRecords()) {
                List<FtbCultivateLearnTaskPhase> phases = phaseMap.get(record.getTaskId());
                record.setPhaseNum((long) phases.size());
                List<FtbCultivateTaskLog> ftbCultivateTaskLogs = completePhaseMap.get(record.getTaskId());
                if (CollUtil.isNotEmpty(ftbCultivateTaskLogs)) {
                    record.setCompletePhaseNum((long) ftbCultivateTaskLogs.size());
                } else {
                    record.setCompletePhaseNum(0L);
                }
            }

//            List<String> completePhaseIds = completePhaseList.stream().map(FtbCultivateTaskLog::getPhaseId).collect(Collectors.toList());
//            List<String> phaseIds = phaseList.stream().map(FtbCultivateLearnTaskPhase::getId).collect(Collectors.toList());
//            boolean b = UserApiV2Util.areListsEqual(completePhaseIds, phaseIds);
        }

        return CultivatePage.coverPageList(taskPage);
    }

    /**
     * App查询我的任务数量
     *
     * @param keyWord 搜索关键字
     * @return 我的任务数量
     */
    @Override
    public Map<String, Integer> queryMyTaskCountForApp(String keyWord) {
//        1-待完成,2-已完成,3-已逾期
        String userId = UserProvider.getUser().getUserId();
        Integer waitCompleteNum = ftbCultivateLearnTaskMapper.queryMyTaskCountForApp(keyWord, userId, StudyStatsEnum.IN_PROGRESS.getCode());
        Integer completeNum = ftbCultivateLearnTaskMapper.queryMyTaskCountForApp(keyWord, userId, StudyStatsEnum.COMPLETED.getCode());
        Integer overNum = ftbCultivateLearnTaskMapper.queryMyTaskCountForApp(keyWord, userId, StudyStatsEnum.OVERDUE.getCode());
        Map<String, Integer> ret = new HashMap<>();
        ret.put("waitCompleteNum", waitCompleteNum);
        ret.put("completeNum", completeNum);
        ret.put("overNum", overNum);
        return ret;
    }


    /**
     * App查询我的任务阶段信息
     *
     * @param myTaskId 我的任务id
     * @param phaseId  阶段ID
     * @return 我的任务阶段信息
     */
    @Override
    public V2CultivateLearnTaskPhaseVo queryMyTaskPhaseInfoForApp(String myTaskId, String phaseId) {
        String userId = UserProvider.getUser().getUserId();

        FtbCultivateLearnTaskAssignment taskAssignment = ftbCultivateLearnTaskAssignmentService.getById(myTaskId);

        if (taskAssignment == null || taskAssignment.getEnableMark() == 1) {
            throw new RuntimeException("任务不存在");
        }

        String taskId = taskAssignment.getTaskId();

        // 根据任务id查询任务信息
        FtbCultivateLearnTask task = ftbCultivateLearnTaskService.getById(taskId);
        if (task == null || task.getEnableMark() == 1) {
            throw new RuntimeException("任务不存在或已被删除");
        }

        // 查询任务的阶段信息
        FtbCultivateLearnTaskPhase phase = ftbCultivateLearnTaskPhaseService.getById(phaseId);
        if (phase == null || phase.getEnableMark() == 1) {
            throw new RuntimeException("任务阶段不存在或已被删除");
        }

        // 构建返回对象
        V2CultivateLearnTaskPhaseVo phaseVo = new V2CultivateLearnTaskPhaseVo();
        phaseVo.setId(phase.getId());
        phaseVo.setTaskId(phase.getTaskId());
        phaseVo.setCertificateExam(phase.getCertificateExam());
        phaseVo.setCertificateIdentification(phase.getCertificateIdentification());
        phaseVo.setQualified(phase.getQualified());
        phaseVo.setIsPassComplete(phase.getIsPassComplete());
        phaseVo.setCreateTime(phase.getCreatorTime());

        // 一次性批量查询所有阶段相关的信息
        // 查询阶段的课程、考试、鉴定、证书、练习信息
        List<FtbCultivateLearnTaskCourseVo> courseList = ftbCultivateLearnTaskCourseService.listByTaskIdAndPhaseId(taskId, phaseId);

        List<FtbCultivateLearnTaskExamVo> examList = ftbCultivateLearnTaskExamService.listByTaskIdAndPhaseId(taskId, phaseId);
        FtbCultivateLearnTaskExamVo exam = CollUtil.isNotEmpty(examList) ? examList.get(0) : null;

        List<FtbCultivateLearnTaskIdentificationVo> identificationList = ftbCultivateLearnTaskIdentificationService.listByTaskIdAndPhaseId(taskId, phaseId);
        FtbCultivateLearnTaskIdentificationVo identification = CollUtil.isNotEmpty(identificationList) ? identificationList.get(0) : null;

        List<FtbCultivateLearnTaskCertificateVo> certificateList = ftbCultivateLearnTaskCertificateService.listByTaskIdAndPhaseId(taskId, phaseId);
        FtbCultivateLearnTaskCertificateVo certificate = CollUtil.isNotEmpty(certificateList) ? certificateList.get(0) : null;

        List<FtbCultivateLearnTaskPracticeVo> practiceList = ftbCultivateLearnTaskPracticeService.listByTaskIdAndPhaseId(taskId, phaseId);

        // 调用封装的批量查询方法
        List<String> courseIds = CollUtil.isNotEmpty(courseList) ? courseList.stream().map(FtbCultivateLearnTaskCourseVo::getCourseId).distinct().collect(Collectors.toList()) : new ArrayList<>();
        List<String> examIds = exam != null ? Collections.singletonList(exam.getExamId()) : new ArrayList<>();
        List<String> identityIds = identification != null ? Collections.singletonList(identification.getIdentificationId()) : new ArrayList<>();
        List<String> certificateIds = certificate != null ? Collections.singletonList(certificate.getCertificateId()) : new ArrayList<>();
        List<String> practiceBusinessIds = CollUtil.isNotEmpty(practiceList) ? practiceList.stream().map(FtbCultivateLearnTaskPracticeVo::getBusinessId).distinct().collect(Collectors.toList()) : new ArrayList<>();

        Map<String, FtbCultivateTaskLog> taskLogsMap = convertTaskLogMap(ftbCultivateTaskLogService.queryCompleteTaskPhase(taskId, userId));

        // 获取用户学习状态
        V2UserLearningStatusResult userStatusResult = CultivateBatchQueryUtil.batchQueryUserLearningStatusWithSpecificIds(
                userId, courseIds, examIds, identityIds, certificateIds, practiceBusinessIds, v2CultivateBatchQueryService, 4, phaseVo.getTaskId());
        Map<String, List<V2ChapterVo>> learningChapterMap = v2CultivateBatchQueryService.batchQueryUserCourseChapterLearnStatus(userId, courseIds);
        // 封装课程信息
        Boolean isCourseComplete = true;
        if (CollUtil.isNotEmpty(courseList)) {
            List<V2CultivateLearnTaskCourseVo> courseVoList = new ArrayList<>();
            Boolean hasNeedCourse = false;//false-没有必须课 true-有必须课
            for (FtbCultivateLearnTaskCourseVo course : courseList) {
                V2CultivateLearnTaskCourseVo courseVo = new V2CultivateLearnTaskCourseVo();
                courseVo.setBusinessSourceId(course.getTaskId());
                courseVo.setBusinessSource(PositionBusinessSourceEnum.TASK_LEARNING);
                courseVo.setId(course.getId());
                courseVo.setCourseId(course.getCourseId());
                courseVo.setIsRequired(course.getIsRequired());
                courseVo.setSortCode(course.getSortCode());
                courseVo.setCourseName(course.getCourseName());
                // 查询课程学习状态 (从批量查询结果中获取)
                FtbCultivatePositionCourceLearning userCourseStatus = userStatusResult.getUserCourseMap().get(course.getCourseId());
                if (userCourseStatus != null) {
                    // 这里可以设置更详细的课程学习状态，比如完成度、是否已学等
                    // 示例：根据实际业务逻辑设置学习状态
                    courseVo.setLearnState(getCourseLearnState(userCourseStatus)); // 根据实际业务逻辑获取学习状态
                } else {
                    courseVo.setLearnState(0); // 默认未学习
                }
                if (courseVo.getIsRequired().equals(0)) {
                    hasNeedCourse = true;
                }
                if (courseVo.getIsRequired().equals(0) && (courseVo.getLearnState().equals(0) || courseVo.getLearnState().equals(2))) {
                    isCourseComplete = false;
                }
                if (courseVo.getLearnState().equals(0)) {
                    courseVo.setLearnProgress("0%");
                } else if (courseVo.getLearnState().equals(1)) {
                    courseVo.setLearnProgress("100%");
                } else {
                    //根据已经学习的章节 和总章节计算
                    List<V2ChapterVo> chapterLearningList = learningChapterMap.get(courseVo.getCourseId());
                    if (CollUtil.isEmpty(chapterLearningList)) {
                        courseVo.setLearnProgress("0%");
                    } else {
                        int total = chapterLearningList.size();
                        int completed = (int) chapterLearningList.stream().filter(chapterLearning -> chapterLearning.getState().equals(1)).count();
                        courseVo.setLearnProgress(String.format("%d%%", completed * 100 / total));
                    }
                }
                courseVoList.add(courseVo);
            }
            if (!hasNeedCourse) {
                isCourseComplete = false;
            }
            phaseVo.setCourseList(courseVoList);
        } else {
            // 如果没有课程列表，说明没有必修课，默认为已完成
            phaseVo.setCourseList(new ArrayList<>());
            isCourseComplete = false;
        }

        // 封装考试信息
        if (exam != null) {
            V2CultivateLearnTaskExamVo examVo = new V2CultivateLearnTaskExamVo();
            examVo.setId(exam.getId());
            examVo.setExamId(exam.getExamId());
            examVo.setExamName(exam.getExamName());
            examVo.setCreatorTime(exam.getCreatorTime());
            examVo.setLastModifyTime(exam.getLastModifyTime());
            examVo.setIsCourseComplete(isCourseComplete);
            // 查询考试状态 (从批量查询结果中获取)
            FtbCultivateExamUser userExamStatus = userStatusResult.getUserExamMap().get(exam.getExamId());
            if (userExamStatus != null) {
                // 这里可以设置更详细的考试状态
                examVo.setExamStatus(getExamStatus(userExamStatus)); // 根据实际业务逻辑获取考试状态
                examVo.setUserExamId(userExamStatus.getId());
            } else {
                examVo.setExamStatus(0); // 默认待考试
                if (isCourseComplete) {
                    userExamStatus = v2CultivateTaskStudyService.checkAndTriggerExam(userId, phaseVo.getTaskId(), phase, Collections.singletonList(exam.getExamId()), userStatusResult.getUserExamMap(),UserProvider.getUser().getTenantId());
                    if (userExamStatus != null) {
                        examVo.setUserExamId(userExamStatus.getId());
                    }
                } else {
                    examVo.setUserExamId(null);
                }
            }
            phaseVo.setExam(examVo);

        }

        // 封装鉴定信息
        if (identification != null) {
            V2CultivateLearnTaskIdentificationVo identificationVo = new V2CultivateLearnTaskIdentificationVo();
            // 获取鉴定信息
            identificationVo.setBusinessSourceId(identification.getTaskId());
            identificationVo.setBusinessSource(PositionBusinessSourceEnum.TASK_LEARNING);
            identificationVo.setId(identification.getId());
            identificationVo.setIdentityId(identification.getIdentificationId());
            identificationVo.setIdentityName(identification.getIdentificationName());
            identificationVo.setCreatorTime(identification.getCreatorTime());
            identificationVo.setLastModifyTime(identification.getLastModifyTime());
            identificationVo.setIsCourseComplete(isCourseComplete);

            // 查询鉴定状态 (从批量查询结果中获取)
            CultivateIdentifyApply userIdentificationStatus = userStatusResult.getUserIdentificationMap().get(identification.getIdentificationId());
            identificationVo.setIsCanIdentification(runCanIdentification(phaseVo, phaseVo.getExam()));
            if (userIdentificationStatus != null) {
                identificationVo.setIdentificationStatus(userIdentificationStatus.getStatus());
                // 这里可以设置更详细的鉴定状态
                identificationVo.setIdentificationResult(getIdentificationStatus(userIdentificationStatus)); // 根据实际业务逻辑获取鉴定状态
                identificationVo.setUserIdentityId(userIdentificationStatus.getId());
            } else {
                identificationVo.setIdentificationStatus(0); // 默认待鉴定
            }
            phaseVo.setIdentification(identificationVo);

        }

        // 封装证书信息
        if (certificate != null) {
            V2CultivateLearnTaskCertificateVo certificateVo = new V2CultivateLearnTaskCertificateVo();
            certificateVo.setId(certificate.getId());
            certificateVo.setCertificateId(certificate.getCertificateId());
            certificateVo.setCertificateName(certificate.getCertName());
            // 查询证书状态 (从批量查询结果中获取)
            FtbCertificateUserEntity userCertificateStatus = userStatusResult.getUserCertificateMap().get(certificate.getCertificateId());
            FtbCultivateTaskLog ftbCultivateTaskLog = taskLogsMap.get(certificate.getPhaseId());
            certificateVo.setIsGet(calIsGetCert(userCertificateStatus, ftbCultivateTaskLog));
            phaseVo.setCertificate(certificateVo);

        }

        // 封装练习信息
        if (CollUtil.isNotEmpty(practiceList)) {
            List<V2CultivateLearnTaskPracticeVo> practiceVoList = new ArrayList<>();
            for (FtbCultivateLearnTaskPracticeVo practice : practiceList) {
                V2CultivateLearnTaskPracticeVo practiceVo = new V2CultivateLearnTaskPracticeVo();
                practiceVo.setId(practice.getId());
                practiceVo.setBusinessId(practice.getBusinessId());
                practiceVo.setBusinessName(practice.getBusinessName());
                practiceVo.setNum(practice.getNum());
                practiceVo.setIsCourseComplete(isCourseComplete);

                // 查询技能完成状态 (从批量查询结果中获取)
                List<String> completeBussinessNum = userStatusResult.getUserSkillMap().get(practice.getBusinessId());
                if (completeBussinessNum != null) {
                    if (completeBussinessNum.size() >= practice.getNum()) {
                        // 这里可以设置更详细的技能完成状态
                        practiceVo.setCompleteNum(practice.getNum()); // 根据实际业务逻辑获取完成数
                        practiceVo.setStatus(1); // 根据实际业务逻辑获取状态
                    } else {
                        practiceVo.setCompleteNum(completeBussinessNum.size());
                        practiceVo.setStatus(0);
                    }
                } else {
                    practiceVo.setCompleteNum(0); // 实际需要查询完成情况
                    practiceVo.setStatus(0); // 实际需要查询完成状态
                }
                practiceVoList.add(practiceVo);

            }
            phaseVo.setPracticeList(practiceVoList);
        } else {
            phaseVo.setPracticeList(new ArrayList<>());
        }

        // 查询阶段状态 (通过日志记录确定) - 使用封装的服务方法
        FtbCultivateTaskLog taskLog = ftbCultivateTaskLogService.getByTaskIdAndUserIdAndPhaseId(taskId, userId, phaseId);

        if (taskLog != null) {
            phaseVo.setPhaseStatus(taskLog.getState());
        } else {
            // 如果没有日志记录，默认为未开始
            phaseVo.setPhaseStatus(0);
        }

        return phaseVo;
    }

    private Integer runCanIdentification(V2CultivateLearnTaskPhaseVo phaseVo,
                                         V2CultivateLearnTaskExamVo examVo) {
        if (phaseVo.getQualified() == 1) {
            if (examVo != null) {
                if (!(examVo.getExamStatus().equals(3)
                        || examVo.getExamStatus().equals(5))) {
                    return 0;
                }
            }
        }
        return 1;
    }

    private Boolean calIsGetCert(FtbCertificateUserEntity userCertificateStatus, FtbCultivateTaskLog ftbCultivateTaskLog) {
        if (ftbCultivateTaskLog == null || ftbCultivateTaskLog.getIssuedCertificate().equals(0)) {
            return false;
        }
        if (ftbCultivateTaskLog.getIssuedCertificate().equals(1)) {
            return true;
        }
        return false;
    }

    private Map<String, FtbCultivateTaskLog> convertTaskLogMap(List<FtbCultivateTaskLog> ftbCultivateTaskLogs) {
        Map<String, FtbCultivateTaskLog> taskLogMap = new HashMap<>();
        if (CollUtil.isEmpty(ftbCultivateTaskLogs)) {
            return taskLogMap;
        }
        for (FtbCultivateTaskLog taskLog : ftbCultivateTaskLogs) {
            taskLogMap.put(taskLog.getPhaseId(), taskLog);
        }
        return taskLogMap;
    }

    @Override
    public Page<V2CultivateJobLearnCourseVo> positionCourseList(V2CultivateCoursePageReq req) {
        Page<V2CultivateJobLearnCourseVo> page = Page.of(req.getCurrentPage(), req.getPageSize());
        return ftbCultivateCourseMapper.queryBindingCourses(page, req);
    }

    // 辅助方法：根据课程学习记录获取学习状态
    private int getCourseLearnState(FtbCultivatePositionCourceLearning courseLearning) {
        // 根据实际业务逻辑设置学习状态
        // 例如：0-未开始，1-学习中，2-已完成
        if (courseLearning == null) {
            return 0; // 未学习
        }
        return courseLearning.getState() != null ? courseLearning.getState() : 0; // 使用实体中的状态
    }

    // 辅助方法：根据考试记录获取考试状态
    private int getExamStatus(FtbCultivateExamUser examUser) {
        // 根据实际业务逻辑设置考试状态
        // 例如：0-未考试，1-考试中，2-已通过，3-未通过
        if (examUser == null) {
            return 0; // 待考试
        }
        return examUser.getStatus() != null ? examUser.getStatus() : 0; // 使用实体中的状态
    }

    // 辅助方法：根据鉴定记录获取鉴定状态
    private int getIdentificationStatus(CultivateIdentifyApply identification) {
        // 根据实际业务逻辑设置鉴定状态
//        鉴定结果(0合格，1优秀，2不合格)
        if (identification == null) {
            return 2; // 待鉴定
        }
        return identification.getResult() != null ? identification.getResult() : 2; // 使用实体中的状态
    }

    // 辅助方法：根据技能记录获取完成数量
    private int getSkillCompleteNum(TeachingRecord skillRecord) {
        // 根据实际业务逻辑设置完成数量
        // 这里可以根据记录存在与否来判断是否完成
        return skillRecord != null ? 1 : 0; // 如果有记录则认为已完成
    }

    // 辅助方法：根据技能记录获取技能状态
    private int getSkillStatus(TeachingRecord skillRecord) {
        // 根据实际业务逻辑设置技能状态
        // 例如：0-未开始，1-进行中，2-已完成
        if (skillRecord == null) {
            return 0; // 未开始
        }
        return 2; // 假设有记录即为已完成
    }

    /**
     * App查询任务阶段信息
     *
     * @param myTaskId 我的任务ID
     * @param userId   用户ID
     * @return
     */
    @Override
    @Transactional
    public void startTask(String myTaskId, String userId) {
        FtbCultivateLearnTaskAssignment task = ftbCultivateLearnTaskAssignmentMapper.selectById(myTaskId);
        if (task == null || task.getEnableMark() == 1) {
            throw new DataException("任务不存在");
        }
        if (!task.getUserId().equals(userId)) {
            throw new DataException("用户无权开启这个任务");
        }
        if (task.getStudyStats() == 1) {
            throw new DataException("任务已开始");
        }
        if (task.getStudyStats() == 2) {
            return;
        }
        if (task.getStudyStats() == 3) {
            throw new DataException("任务已逾期");
        }

        String taskId = task.getTaskId();
        FtbCultivateLearnTask ftbCultivateLearnTask = ftbCultivateLearnTaskMapper.selectById(taskId);
        if (ftbCultivateLearnTask == null || ftbCultivateLearnTask.getEnableMark() == 1) {
            throw new DataException("任务不存在,或被删除");
        }
        if (ftbCultivateLearnTask.getStatus().equals(4)) {
            throw new DataException("任务已终止");
        }
        if (ftbCultivateLearnTask.getStatus().equals(3)) {
            throw new DataException("任务已结束");
        }
        if (ftbCultivateLearnTask.getTaskType().equals(1)) {
            //帮我判断任务是否开始 和结束
            if (ftbCultivateLearnTask.getTimeLimitStartTime().after(new Date())) {
                throw new DataException("任务还未到开始时间");
            }
            if (ftbCultivateLearnTask.getTimeLimitEndTime().before(new Date())) {
                task.setStudyStats(3);
            }
        }
        task.setLearningStartTime(new Date());
        task.setStudyStats(1);
        ftbCultivateLearnTaskAssignmentMapper.updateById(task);
        //开始记录第一阶段正在学习中
        initUserPhaseLog(taskId, userId);
    }

    /**
     * App修改任务状态
     *
     * @param tenantId 租户ID
     */
    @Override
    public void checkAndUpdateTaskStatus(String tenantId) {
        try {
            Date now = new Date();
            //修改进行中
            LambdaQueryWrapper<FtbCultivateLearnTask> wrapper = new LambdaQueryWrapper<>();
            wrapper.le(FtbCultivateLearnTask::getTimeLimitStartTime, now)
                    .ge(FtbCultivateLearnTask::getTimeLimitEndTime, now)
                    .eq(FtbCultivateLearnTask::getStatus, 1)
                    .eq(FtbCultivateLearnTask::getTaskType, 1)
                    .eq(FtbCultivateLearnTask::getEnableMark, 0);
            List<FtbCultivateLearnTask> taskList = ftbCultivateLearnTaskMapper.selectList(wrapper);
            if (CollUtil.isNotEmpty(taskList)) {
                //获取任务ids集合
                List<String> taskIds = taskList.stream().map(FtbCultivateLearnTask::getId).collect(Collectors.toList());
                LambdaUpdateWrapper<FtbCultivateLearnTask> taskLambdaUpdateWrapperStart = new LambdaUpdateWrapper<FtbCultivateLearnTask>()
                        .set(FtbCultivateLearnTask::getStatus, 2)
                        .in(FtbCultivateLearnTask::getId, taskIds)
                        .eq(FtbCultivateLearnTask::getEnableMark, 0);
                ftbCultivateLearnTaskMapper.update(null, taskLambdaUpdateWrapperStart);
                cultivateTaskLeanAsyncDealUtil.asyncSendStartTaskLearningAlert(taskList, tenantId);
                courseStudyUtil.addTaskCourseStudyRecord(taskIds, tenantId);
            }
            //修改结束
            LambdaUpdateWrapper<FtbCultivateLearnTask> taskLambdaUpdateWrapperOver = new LambdaUpdateWrapper<FtbCultivateLearnTask>()
                    .set(FtbCultivateLearnTask::getStatus, 3)
                    .le(FtbCultivateLearnTask::getTimeLimitEndTime, now)
                    .in(FtbCultivateLearnTask::getStatus, 1, 2)
                    .eq(FtbCultivateLearnTask::getTaskType, 1)
                    .eq(FtbCultivateLearnTask::getEnableMark, 0);
            ftbCultivateLearnTaskMapper.update(null, taskLambdaUpdateWrapperOver);
            //异步处理所有用户任务的状态
            cultivateTaskLeanAsyncDealUtil.asyncUpdateUserTaskStatus(tenantId);
            //如果处理长期任务 显示
            checkAndUpdateOverdueUserTasksForLong(tenantId);
            //处理限时任务  再限时 用户开始后 根据用户开始任务时间，把限时改成已逾期
            checkAndUpdateOverdueUserTasksForTimeLimited(tenantId);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public V2MyCultivateLearnTaskSimpleInfoVo queryMyTaskSimpleInfoForApp(String myTaskId) {
        String userId = UserProvider.getUser().getUserId();
        V2MyCultivateLearnTaskSimpleInfoVo taskSimpleInfo = new V2MyCultivateLearnTaskSimpleInfoVo();

        LambdaQueryWrapper<FtbCultivateLearnTaskAssignment> assignmentWrapper = Wrappers.lambdaQuery();
        assignmentWrapper.select(FtbCultivateLearnTaskAssignment::getId,
                FtbCultivateLearnTaskAssignment::getTaskId,
                FtbCultivateLearnTaskAssignment::getUserId,
                FtbCultivateLearnTaskAssignment::getStudyStats,
                FtbCultivateLearnTaskAssignment::getLearningStartTime,
                FtbCultivateLearnTaskAssignment::getLearningEndTime);
        assignmentWrapper.eq(FtbCultivateLearnTaskAssignment::getId, myTaskId);
        assignmentWrapper.eq(FtbCultivateLearnTaskAssignment::getUserId, userId);
        assignmentWrapper.eq(FtbCultivateLearnTaskAssignment::getEnableMark, 0);
        FtbCultivateLearnTaskAssignment taskAssignment = ftbCultivateLearnTaskAssignmentService.getOne(assignmentWrapper);
        if (taskAssignment == null) {
            throw new RuntimeException("对不起,你的任务已经不存在了");
        }
        // 查询任务详情
        String taskId = taskAssignment.getTaskId();
        FtbCultivateLearnTask task = ftbCultivateLearnTaskService.getById(taskId);
        if (task == null || task.getEnableMark() == 1) {
            throw new RuntimeException("对不起,任务删除了");
        }

        // 构建任务基础信息
        taskSimpleInfo.setId(taskAssignment.getId());
        taskSimpleInfo.setTaskId(task.getId());
        taskSimpleInfo.setStudyStats(taskAssignment.getStudyStats());
        taskSimpleInfo.setTaskClass(task.getTaskClass());
        taskSimpleInfo.setTaskName(task.getTaskName());
        taskSimpleInfo.setTaskType(task.getTaskType());
        taskSimpleInfo.setTimeLimitStartTime(task.getTimeLimitStartTime());
        taskSimpleInfo.setTimeLimitEndTime(task.getTimeLimitEndTime());
        taskSimpleInfo.setStudentTimeCompletion(task.getStudentTimeCompletion());
        taskSimpleInfo.setTimeCompletionUnit(task.getTimeCompletionUnit());
        taskSimpleInfo.setTimeCompletionDays(task.getTimeCompletionDays());
        taskSimpleInfo.setAssignmentRule(task.getAssignmentRule());
        taskSimpleInfo.setAssociationIds(task.getAssociationIds());
        taskSimpleInfo.setStartEntryPeriod(task.getStartEntryPeriod());
        taskSimpleInfo.setEndEntryPeriod(task.getEndEntryPeriod());
        taskSimpleInfo.setCustomAssignType(task.getCustomAssignType());
        taskSimpleInfo.setCustomAssignPostIds(task.getCustomAssignPostIds());
        taskSimpleInfo.setDescription(task.getDescription());
        taskSimpleInfo.setCoverId(task.getCoverId());
        taskSimpleInfo.setCoverUrl(task.getCoverUrl());
        taskSimpleInfo.setStatus(task.getStatus());


        // 查询任务阶段列表
        LambdaQueryWrapper<FtbCultivateLearnTaskPhase> phaseWrapper = Wrappers.lambdaQuery();
        phaseWrapper.eq(FtbCultivateLearnTaskPhase::getTaskId, taskId);
        phaseWrapper.eq(FtbCultivateLearnTaskPhase::getEnableMark, 0);
        List<FtbCultivateLearnTaskPhase> phaseList = ftbCultivateLearnTaskPhaseService.list(phaseWrapper);

        // 将数据库实体转换为VO，并确定每个阶段的状态
        List<V2CultivateLearnTaskSimplePhaseVo> phaseVoList = new ArrayList<>();

        // 一次性查询所有阶段的日志，提高性能
        LambdaQueryWrapper<FtbCultivateTaskLog> logWrapper = Wrappers.lambdaQuery();
        logWrapper.eq(FtbCultivateTaskLog::getTaskId, taskId);
        logWrapper.eq(FtbCultivateTaskLog::getUserId, userId);
        logWrapper.eq(FtbCultivateTaskLog::getEnabledMark, 0);
        List<FtbCultivateTaskLog> allLogs = ftbCultivateTaskLogService.list(logWrapper);

        // allLogs 转换成key是id的map
        Map<String, FtbCultivateTaskLog> logsMap = allLogs.stream().collect(Collectors.toMap(FtbCultivateTaskLog::getPhaseId, log -> log));

        String currStudyPhase = phaseList.get(0).getId();
        for (FtbCultivateLearnTaskPhase phase : phaseList) {
            V2CultivateLearnTaskSimplePhaseVo phaseVo = new V2CultivateLearnTaskSimplePhaseVo();
            phaseVo.convert(phase);
            FtbCultivateTaskLog ftbCultivateTaskLog = logsMap.get(phase.getId());
            if (ftbCultivateTaskLog != null) {
                phaseVo.setPhaseStatus(ftbCultivateTaskLog.getState());
                currStudyPhase = phase.getId();
            } else {
                phaseVo.setPhaseStatus(0);
            }
            phaseVoList.add(phaseVo);
        }

        taskSimpleInfo.setPhase(phaseVoList);
        taskSimpleInfo.setCurrStudyPhase(currStudyPhase);

        return taskSimpleInfo;
    }

    @Override
    public List<V2CultivateLearnTaskPhaseVo> queryUserTaskInfo(String myTaskId) {
        FtbCultivateLearnTaskAssignment taskAssignment = ftbCultivateLearnTaskAssignmentService.getById(myTaskId);
        if (taskAssignment == null || taskAssignment.getEnableMark().equals(1)) {
            throw new RuntimeException("该数据已经不存在");
        }
        String userId = taskAssignment.getUserId();
        // 查询任务详情
        String taskId = taskAssignment.getTaskId();
        FtbCultivateLearnTask task = ftbCultivateLearnTaskService.getById(taskId);
        if (task == null || task.getEnableMark().equals(1)) {
            throw new RuntimeException("对不起,任务删除了");
        }
        List<V2CultivateLearnTaskPhaseVo> returnList = new ArrayList<>();
        // 查询任务阶段列表
        LambdaQueryWrapper<FtbCultivateLearnTaskPhase> phaseWrapper = Wrappers.lambdaQuery();
        phaseWrapper.eq(FtbCultivateLearnTaskPhase::getTaskId, taskId)
                .eq(FtbCultivateLearnTaskPhase::getEnableMark, 0);
        List<FtbCultivateLearnTaskPhase> phaseList = ftbCultivateLearnTaskPhaseService.list(phaseWrapper);
        Map<String, FtbCultivateLearnTaskPhase> phaseMap = new HashMap<>();
        // 转出 V2CultivateLearnTaskPhaseVo
        List<V2CultivateLearnTaskPhaseVo> phaseVoList = phaseList.stream().map(phase -> {
            phaseMap.put(phase.getId(), phase);
            V2CultivateLearnTaskPhaseVo phaseVo = new V2CultivateLearnTaskPhaseVo();
            phaseVo.convert(phase);
            return phaseVo;
        }).collect(Collectors.toList());

        // 一次性批量查询所有阶段相关的信息
        // 查询阶段的课程、考试、鉴定、证书、练习信息
        List<FtbCultivateLearnTaskCourseVo> courseList = ftbCultivateLearnTaskCourseService.listByTaskId(taskId, null);

        List<FtbCultivateLearnTaskExamVo> examList = ftbCultivateLearnTaskExamService.listByTaskId(taskId);

        List<FtbCultivateLearnTaskIdentificationVo> identificationList = ftbCultivateLearnTaskIdentificationService.listByTaskId(taskId);

        List<FtbCultivateLearnTaskCertificateVo> certificateList = ftbCultivateLearnTaskCertificateService.listByTaskId(taskId);

        List<FtbCultivateLearnTaskPracticeVo> practiceList = ftbCultivateLearnTaskPracticeService.listByTaskId(taskId);


        //按阶段分组 对课程 考试 鉴定 证书 练习
        Map<String, List<FtbCultivateLearnTaskCourseVo>> courseMap = courseList.stream().collect(Collectors.groupingBy(FtbCultivateLearnTaskCourseVo::getPhaseId));
        Map<String, List<FtbCultivateLearnTaskExamVo>> examMap = examList.stream().collect(Collectors.groupingBy(FtbCultivateLearnTaskExamVo::getPhaseId));
        Map<String, List<FtbCultivateLearnTaskIdentificationVo>> identificationMap = identificationList.stream().collect(Collectors.groupingBy(FtbCultivateLearnTaskIdentificationVo::getPhaseId));
        Map<String, List<FtbCultivateLearnTaskCertificateVo>> certificateMap = certificateList.stream().collect(Collectors.groupingBy(FtbCultivateLearnTaskCertificateVo::getPhaseId));
        Map<String, List<FtbCultivateLearnTaskPracticeVo>> practiceMap = practiceList.stream().collect(Collectors.groupingBy(FtbCultivateLearnTaskPracticeVo::getPhaseId));

        Map<String, FtbCultivateTaskLog> taskLogsMap = convertTaskLogMap(ftbCultivateTaskLogService.queryCompleteTaskPhase(taskId, userId));
        Map<String, List<V2ChapterVo>> learningChapterMap = v2CultivateBatchQueryService.batchQueryUserCourseChapterLearnStatus(userId, courseList.stream().map(FtbCultivateLearnTaskCourseVo::getCourseId).collect(Collectors.toList()));

        for (V2CultivateLearnTaskPhaseVo phaseVo : phaseVoList) {
            String phaseId = phaseVo.getId();
            List<FtbCultivateLearnTaskCourseVo> taskCourseList = courseMap.get(phaseId);
            List<FtbCultivateLearnTaskExamVo> ftbCultivateLearnTaskExams = examMap.get(phaseId);
            List<FtbCultivateLearnTaskIdentificationVo> ftbCultivateLearnTaskIdentifications = identificationMap.get(phaseId);
            List<FtbCultivateLearnTaskCertificateVo> ftbCultivateLearnTaskCertificates = certificateMap.get(phaseId);
            List<FtbCultivateLearnTaskPracticeVo> ftbCultivateLearnTaskPractices = practiceMap.get(phaseId);

            List<String> courseIds = new ArrayList<>();
            if (CollUtil.isNotEmpty(taskCourseList)) {
                courseIds = taskCourseList.stream().map(FtbCultivateLearnTaskCourseVo::getCourseId).collect(Collectors.toList());
            }

            List<String> examIds = new ArrayList<>();
            if (CollUtil.isNotEmpty(ftbCultivateLearnTaskExams)) {
                examIds = ftbCultivateLearnTaskExams.stream().map(FtbCultivateLearnTaskExamVo::getExamId).collect(Collectors.toList());
            }
            List<String> identityIds = new ArrayList<>();
            if (CollUtil.isNotEmpty(ftbCultivateLearnTaskIdentifications)) {
                identityIds = ftbCultivateLearnTaskIdentifications.stream().map(FtbCultivateLearnTaskIdentificationVo::getIdentificationId).collect(Collectors.toList());
            }
            List<String> certificateIds = new ArrayList<>();
            if (CollUtil.isNotEmpty(ftbCultivateLearnTaskCertificates)) {
                certificateIds = ftbCultivateLearnTaskCertificates.stream().map(FtbCultivateLearnTaskCertificateVo::getCertificateId).collect(Collectors.toList());
            }
            List<String> practiceBusinessIds = new ArrayList<>();
            if (CollUtil.isNotEmpty(ftbCultivateLearnTaskPractices)) {
                practiceBusinessIds = ftbCultivateLearnTaskPractices.stream().map(FtbCultivateLearnTaskPracticeVo::getBusinessId).collect(Collectors.toList());
            }
            // 获取用户学习状态
            V2UserLearningStatusResult userStatusResult = CultivateBatchQueryUtil.batchQueryUserLearningStatusWithSpecificIds(
                    userId, courseIds, examIds, identityIds, certificateIds, practiceBusinessIds, v2CultivateBatchQueryService, 4, phaseVo.getTaskId());

            // 封装课程信息
            if (CollUtil.isNotEmpty(taskCourseList)) {
                List<V2CultivateLearnTaskCourseVo> courseVoList = new ArrayList<>();
                for (FtbCultivateLearnTaskCourseVo course : taskCourseList) {
                    V2CultivateLearnTaskCourseVo courseVo = new V2CultivateLearnTaskCourseVo();
                    courseVo.setBusinessSourceId(course.getTaskId());
                    courseVo.setBusinessSource(PositionBusinessSourceEnum.TASK_LEARNING);
                    courseVo.setId(course.getId());
                    courseVo.setCourseId(course.getCourseId());
                    courseVo.setIsRequired(course.getIsRequired());
                    courseVo.setSortCode(course.getSortCode());
                    courseVo.setCourseName(course.getCourseName());
                    // 查询课程学习状态 (从批量查询结果中获取)
                    FtbCultivatePositionCourceLearning userCourseStatus = userStatusResult.getUserCourseMap().get(course.getCourseId());
                    if (userCourseStatus != null) {
                        // 这里可以设置更详细的课程学习状态，比如完成度、是否已学等
                        // 示例：根据实际业务逻辑设置学习状态
                        courseVo.setLearnState(getCourseLearnState(userCourseStatus)); // 根据实际业务逻辑获取学习状态
                        courseVo.setLearnTime(userCourseStatus.getLearnTime());
                    } else {
                        courseVo.setLearnState(0); // 默认未学习
                        courseVo.setLearnTime(0);
                    }
                    if (courseVo.getLearnState().equals(0)) {
                        courseVo.setLearnProgress("0%");
                    } else if (courseVo.getLearnState().equals(1)) {
                        courseVo.setLearnProgress("100%");
                    } else {
                        //根据已经学习的章节 和总章节计算
                        List<V2ChapterVo> chapterLearningList = learningChapterMap.get(courseVo.getCourseId());
                        if (CollUtil.isEmpty(chapterLearningList)) {
                            courseVo.setLearnProgress("0%");
                        } else {
                            int total = chapterLearningList.size();
                            int completed = (int) chapterLearningList.stream().filter(chapterLearning -> chapterLearning.getState().equals(1)).count();
                            courseVo.setLearnProgress(String.format("%d%%", completed * 100 / total));
                        }
                    }
                    courseVoList.add(courseVo);
                }
                phaseVo.setCourseList(courseVoList);
            }


            // 封装考试信息
            if (ftbCultivateLearnTaskExams != null) {
                V2CultivateLearnTaskExamVo examVo = new V2CultivateLearnTaskExamVo();
                FtbCultivateLearnTaskExamVo ftbCultivateLearnTaskExam = ftbCultivateLearnTaskExams.get(0);
                // 获取考试信息
                examVo.setId(ftbCultivateLearnTaskExam.getId());
                examVo.setExamId(ftbCultivateLearnTaskExam.getExamId());
                examVo.setExamName(ftbCultivateLearnTaskExam.getExamName());
                // 查询考试状态 (从批量查询结果中获取)
                FtbCultivateExamUser userExamStatus = userStatusResult.getUserExamMap().get(ftbCultivateLearnTaskExam.getExamId());
                if (userExamStatus != null) {
                    // 这里可以设置更详细的考试状态
                    examVo.setExamStatus(getExamStatus(userExamStatus)); // 根据实际业务逻辑获取考试状态
                    examVo.setUserExamId(userExamStatus.getId());
                    examVo.setUserExamDuration(userExamStatus.getDuration());
                } else {
                    examVo.setExamStatus(0); // 默认待考试
                    examVo.setUserExamDuration(0L);
                    examVo.setUserExamId(null);
                }
                phaseVo.setExam(examVo);

            }

            // 封装鉴定信息
            if (ftbCultivateLearnTaskIdentifications != null) {
                V2CultivateLearnTaskIdentificationVo identificationVo = new V2CultivateLearnTaskIdentificationVo();
                // 获取鉴定信息
                FtbCultivateLearnTaskIdentificationVo ftbCultivateLearnTaskIdentification = ftbCultivateLearnTaskIdentifications.get(0);

                identificationVo.setBusinessSourceId(ftbCultivateLearnTaskIdentification.getTaskId());
                identificationVo.setBusinessSource(PositionBusinessSourceEnum.TASK_LEARNING);
                identificationVo.setId(ftbCultivateLearnTaskIdentification.getId());
                identificationVo.setIdentityId(ftbCultivateLearnTaskIdentification.getIdentificationId());
                identificationVo.setIdentityName(ftbCultivateLearnTaskIdentification.getIdentificationName());
                // 查询鉴定状态 (从批量查询结果中获取)
                CultivateIdentifyApply userIdentificationStatus = userStatusResult.getUserIdentificationMap().get(ftbCultivateLearnTaskIdentification.getIdentificationId());
                if (userIdentificationStatus != null) {
                    identificationVo.setIdentificationStatus(userIdentificationStatus.getStatus());
                    // 这里可以设置更详细的鉴定状态
                    identificationVo.setIdentificationResult(getIdentificationStatus(userIdentificationStatus)); // 根据实际业务逻辑获取鉴定状态
                    identificationVo.setUserIdentityId(userIdentificationStatus.getId());
                    identificationVo.setUseTime(userIdentificationStatus.getUseTime());
                } else {
                    identificationVo.setIdentificationStatus(0); // 默认待鉴定
                    identificationVo.setUserIdentityId(null);
                    identificationVo.setUseTime(0);
                }

                phaseVo.setIdentification(identificationVo);

            }

            // 封装证书信息
            if (ftbCultivateLearnTaskCertificates != null) {
                V2CultivateLearnTaskCertificateVo certificateVo = new V2CultivateLearnTaskCertificateVo();
                FtbCultivateLearnTaskCertificateVo ftbCultivateLearnTaskCertificate = ftbCultivateLearnTaskCertificates.get(0);

                certificateVo.setId(ftbCultivateLearnTaskCertificate.getId());
                certificateVo.setCertificateId(ftbCultivateLearnTaskCertificate.getCertificateId());
                certificateVo.setCertificateName(ftbCultivateLearnTaskCertificate.getCertName());
                // 查询证书状态 (从批量查询结果中获取)
                FtbCertificateUserEntity userCertificateStatus = userStatusResult.getUserCertificateMap().get(ftbCultivateLearnTaskCertificate.getCertificateId());
                FtbCultivateTaskLog ftbCultivateTaskLog = taskLogsMap.get(phaseId);
                certificateVo.setIsGet(calIsGetCert(userCertificateStatus, ftbCultivateTaskLog));
                phaseVo.setCertificate(certificateVo);

            }

            // 封装练习信息
            if (CollUtil.isNotEmpty(ftbCultivateLearnTaskPractices)) {
                List<V2CultivateLearnTaskPracticeVo> practiceVoList = new ArrayList<>();
                for (FtbCultivateLearnTaskPracticeVo practice : ftbCultivateLearnTaskPractices) {
                    V2CultivateLearnTaskPracticeVo practiceVo = new V2CultivateLearnTaskPracticeVo();
                    // 从缓存中获取技能名称

                    practiceVo.setId(practice.getId());
                    practiceVo.setBusinessId(practice.getBusinessId());
                    practiceVo.setBusinessName(practice.getBusinessName());
                    practiceVo.setNum(practice.getNum());

                    // 查询技能完成状态 (从批量查询结果中获取)
                    List<String> completeBussinessNum = userStatusResult.getUserSkillMap().get(practice.getBusinessId());
                    if (completeBussinessNum != null) {
                        if (completeBussinessNum.size() >= practice.getNum()) {
                            // 这里可以设置更详细的技能完成状态
                            practiceVo.setCompleteNum(practice.getNum()); // 根据实际业务逻辑获取完成数
                            practiceVo.setStatus(1); // 根据实际业务逻辑获取状态
                        } else {
                            practiceVo.setCompleteNum(completeBussinessNum.size());
                            practiceVo.setStatus(0);
                        }
                    } else {
                        practiceVo.setCompleteNum(0); // 实际需要查询完成情况
                        practiceVo.setStatus(0); // 实际需要查询完成状态
                    }
                    practiceVoList.add(practiceVo);

                }
                phaseVo.setPracticeList(practiceVoList);
            } else {
                phaseVo.setPracticeList(new ArrayList<>());
            }

            // 查询阶段状态 (通过日志记录确定) - 使用封装的服务方法
            FtbCultivateTaskLog taskLog = ftbCultivateTaskLogService.getByTaskIdAndUserIdAndPhaseId(taskId, userId, phaseId);

            if (taskLog != null) {
                phaseVo.setPhaseStatus(taskLog.getState());
            } else {
                // 如果没有日志记录，默认为未开始
                phaseVo.setPhaseStatus(0);
            }
            returnList.add(phaseVo);
        }
        return returnList;
    }


    /**
     * 根据任务名称查询任务数量
     *
     * @param taskName 任务名称
     * @return 任务数量
     */
    public Long queryTaskNumByName(String taskName) {
        LambdaQueryWrapper<FtbCultivateLearnTask> taskQueryWrapper = Wrappers.lambdaQuery();
        taskQueryWrapper.eq(FtbCultivateLearnTask::getTaskName, taskName);
        taskQueryWrapper.eq(FtbCultivateLearnTask::getEnableMark, 0);
        return ftbCultivateLearnTaskService.count(taskQueryWrapper);
    }

    public FtbCultivateLearnTask queryTaskInfoByName(String taskName) {
        LambdaQueryWrapper<FtbCultivateLearnTask> taskNameQueryWrapper = Wrappers.lambdaQuery();
        taskNameQueryWrapper.eq(FtbCultivateLearnTask::getTaskName, taskName);
        taskNameQueryWrapper.eq(FtbCultivateLearnTask::getEnableMark, 0);
        List<FtbCultivateLearnTask> list = ftbCultivateLearnTaskService.list(taskNameQueryWrapper);
        if (CollUtil.isNotEmpty(list)) {
            return list.get(0);
        }
        return null;

    }

    /**
     * 初始化用户任务的阶段
     * 当用户开始任务时，自动标记第一阶段为进行中状态
     *
     * @param taskId 任务ID
     * @param userId 用户ID
     */
    private void initUserPhaseLog(String taskId, String userId) {
        // 查询任务的第一个阶段
        LambdaQueryWrapper<FtbCultivateLearnTaskPhase> phaseQueryWrapper = Wrappers.lambdaQuery();
        phaseQueryWrapper.eq(FtbCultivateLearnTaskPhase::getTaskId, taskId)
                .eq(FtbCultivateLearnTaskPhase::getEnableMark, 0)
                .orderByAsc(FtbCultivateLearnTaskPhase::getCreatorTime); // 按创建时间排序，获取第一个阶段
        List<FtbCultivateLearnTaskPhase> phases = ftbCultivateLearnTaskPhaseService.list(phaseQueryWrapper);
        if (CollUtil.isNotEmpty(phases)) {
            // 检查是否已存在该阶段的日志记录
            LambdaQueryWrapper<FtbCultivateTaskLog> logQueryWrapper = Wrappers.lambdaQuery();
            logQueryWrapper.eq(FtbCultivateTaskLog::getTaskId, taskId)
                    .eq(FtbCultivateTaskLog::getUserId, userId)
                    .eq(FtbCultivateTaskLog::getEnabledMark, 0);
            ftbCultivateTaskLogService.remove(logQueryWrapper);
            FtbCultivateLearnTaskPhase phase = phases.get(0);
            FtbCultivateTaskLog taskLog = new FtbCultivateTaskLog();
            taskLog.setTaskId(taskId);
            taskLog.setPhaseId(phase.getId());
            taskLog.setUserId(userId);
            taskLog.setState(1); // 1表示正在进行中
            ftbCultivateTaskLogService.save(taskLog);
        }
    }

    /**
     * 检查考试是否被学习任务绑定
     *
     * @param examId 考试ID
     * @return true-已绑定 false-未绑定
     */
    @Override
    public Boolean checkExamBinding(String examId) {
        return ftbCultivateLearnTaskExamService.checkExamBinding(examId);
    }


    @Override
    public CheckUserTaskAllPhasesCompleteVo checkUserTaskAllPhasesComplete(String userTaskId) {
        // 1. 查询用户任务分配信息，获取用户ID和任务ID
        FtbCultivateLearnTaskAssignment assignment = ftbCultivateLearnTaskAssignmentMapper.selectById(userTaskId);
        if (assignment == null) {
            throw new DataException("用户任务不存在");
        }

        String userId = assignment.getUserId();
        String taskId = assignment.getTaskId();

        // 2. 查询该任务的所有阶段
        LambdaQueryWrapper<FtbCultivateLearnTaskPhase> phaseWrapper = Wrappers.lambdaQuery();
        phaseWrapper.eq(FtbCultivateLearnTaskPhase::getTaskId, taskId)
                .eq(FtbCultivateLearnTaskPhase::getEnableMark, 0)
                .orderByAsc(FtbCultivateLearnTaskPhase::getCreatorTime);
        List<FtbCultivateLearnTaskPhase> phases = ftbCultivateLearnTaskPhaseMapper.selectList(phaseWrapper);

        // 3. 批量查询所有阶段的日志记录（优化：循环外查询）
        Map<String, FtbCultivateTaskLog> taskLogMap = new HashMap<>();
        if (CollUtil.isNotEmpty(phases)) {
            List<String> phaseIds = phases.stream()
                    .map(FtbCultivateLearnTaskPhase::getId)
                    .collect(Collectors.toList());

            // 批量查询该用户在该任务下所有阶段的日志
            LambdaQueryWrapper<FtbCultivateTaskLog> logWrapper = Wrappers.lambdaQuery();
            logWrapper.eq(FtbCultivateTaskLog::getTaskId, taskId)
                    .eq(FtbCultivateTaskLog::getUserId, userId)
                    .in(FtbCultivateTaskLog::getPhaseId, phaseIds);
            List<FtbCultivateTaskLog> taskLogs = ftbCultivateTaskLogService.list(logWrapper);

            // 将日志列表转换为 Map，key 为 phaseId
            taskLogMap = taskLogs.stream()
                    .collect(Collectors.toMap(FtbCultivateTaskLog::getPhaseId, log -> log, (k1, k2) -> k1));
        }

        // 4. 构建返回结果
        List<CheckUserTaskAllPhasesCompleteVo.PhaseCompleteInfo> phaseCompleteInfos = new ArrayList<>();

        for (FtbCultivateLearnTaskPhase phase : phases) {
            // 从 Map 中获取该阶段的日志记录
            FtbCultivateTaskLog taskLog = taskLogMap.get(phase.getId());

            CheckUserTaskAllPhasesCompleteVo.PhaseCompleteInfo phaseInfo;
            if (taskLog != null) {
                // 阶段状态：根据state字段判断（1-已完成）
                Integer state = taskLog.getState();
                boolean isComplete = state != null && state == 2;

                phaseInfo = CheckUserTaskAllPhasesCompleteVo.PhaseCompleteInfo.builder()
                        .phaseId(phase.getId())
                        .isComplete(isComplete)
                        .phaseStatus(state)
                        .courseState(taskLog.getCourseState())
                        .examState(taskLog.getExamState())
                        .practiceState(taskLog.getPracticeState())
                        .identifyState(taskLog.getIdentifyState())
                        .issuedCertificate(taskLog.getIssuedCertificate())
                        .build();
            } else {
                // 如果没有日志记录，说明阶段还未开始
                phaseInfo = CheckUserTaskAllPhasesCompleteVo.PhaseCompleteInfo.builder()
                        .phaseId(phase.getId())
                        .isComplete(false)
                        .phaseStatus(0) // 0-未开始
                        .courseState(-1) // -1-未配置
                        .examState(-1)
                        .practiceState(-1)
                        .identifyState(-1)
                        .issuedCertificate(0)
                        .build();
            }

            phaseCompleteInfos.add(phaseInfo);
        }

        return CheckUserTaskAllPhasesCompleteVo.builder()
                .userTaskId(userTaskId)
                .phases(phaseCompleteInfos)
                .build();
    }

    /**
     * 检查并更新限时任务的用户学习状态为已逾期
     * 针对长期任务 显示的情况
     * 将已经超时的用户任务状态更新为已逾期(studyStats=3)
     *
     * @param tenantId 租户ID
     */
    private void checkAndUpdateOverdueUserTasksForLong(String tenantId) {
        try {
            Date now = new Date();

            // 查询所有限时任务(studentTimeCompletion=0)且状态为进行中的任务
            LambdaQueryWrapper<FtbCultivateLearnTask> taskWrapper = Wrappers.lambdaQuery();
            taskWrapper.eq(FtbCultivateLearnTask::getTaskType, 0);
            taskWrapper.eq(FtbCultivateLearnTask::getStudentTimeCompletion, 0); // 0-限时
            taskWrapper.eq(FtbCultivateLearnTask::getEnableMark, 0); // 有效
            taskWrapper.in(FtbCultivateLearnTask::getStatus, 2); // 2-进行中
            List<FtbCultivateLearnTask> timeLimitedTasks = ftbCultivateLearnTaskService.list(taskWrapper);

            if (CollUtil.isEmpty(timeLimitedTasks)) {
                return;
            }

            // 获取这些任务的ID列表
            List<String> taskIds = timeLimitedTasks.stream()
                    .map(FtbCultivateLearnTask::getId)
                    .collect(Collectors.toList());

            // 批量查询这些任务下的所有用户任务分配记录
            LambdaQueryWrapper<FtbCultivateLearnTaskAssignment> assignmentWrapper = Wrappers.lambdaQuery();
            assignmentWrapper.in(FtbCultivateLearnTaskAssignment::getTaskId, taskIds);
            assignmentWrapper.eq(FtbCultivateLearnTaskAssignment::getEnableMark, 0); // 有效
            assignmentWrapper.eq(FtbCultivateLearnTaskAssignment::getStudyStats, 1); // 0-未开始, 1-进行中
            assignmentWrapper.isNotNull(FtbCultivateLearnTaskAssignment::getLearningStartTime); // 有开始时间
            List<FtbCultivateLearnTaskAssignment> assignments = ftbCultivateLearnTaskAssignmentService.list(assignmentWrapper);

            if (CollUtil.isEmpty(assignments)) {
                return;
            }

            // 构建taskId到Task的映射
            Map<String, FtbCultivateLearnTask> taskMap = timeLimitedTasks.stream()
                    .collect(Collectors.toMap(FtbCultivateLearnTask::getId, task -> task));

            // 需要更新为逾期的用户任务ID列表
            List<String> overdueAssignmentIds = new ArrayList<>();


            for (FtbCultivateLearnTaskAssignment assignment : assignments) {
                // 计算用户应该完成的时间 = 开始学习时间 + 限时时长
                Date learningStartTime = assignment.getLearningStartTime();
                if (learningStartTime == null) {
                    continue;
                }
                FtbCultivateLearnTask task = taskMap.get(assignment.getTaskId());
                if (task == null) {
                    continue;
                }
                if (task.getTimeCompletionUnit() == null || task.getTimeCompletionUnit() < 0) {
                    continue;
                }
                if (task.getTimeCompletionDays() == null || task.getTimeCompletionDays() <= 0) {
                    continue;
                }


                // 计算任务的限时时长（毫秒）
                long timeLimitMillis = calculateTimeLimitMillis(task);
                if (timeLimitMillis <= 0) {
                    continue; // 无法计算有效限时时长，跳过
                }


                long deadlineMillis = learningStartTime.getTime() + timeLimitMillis;
                Date deadline = new Date(deadlineMillis);

                // 如果当前时间已经超过截止时间，则标记为逾期
                if (now.after(deadline)) {
                    overdueAssignmentIds.add(assignment.getId());
                }
            }

            // 批量更新逾期状态
            if (CollUtil.isNotEmpty(overdueAssignmentIds)) {
                LambdaUpdateWrapper<FtbCultivateLearnTaskAssignment> updateWrapper = Wrappers.lambdaUpdate();
                updateWrapper.set(FtbCultivateLearnTaskAssignment::getStudyStats, StudyStatsEnum.OVERDUE.getCode()); // 3-已逾期
                updateWrapper.in(FtbCultivateLearnTaskAssignment::getId, overdueAssignmentIds);
                ftbCultivateLearnTaskAssignmentService.update(updateWrapper);

                log.info("租户[{}]限时任务逾期检查完成，共更新{}条用户任务为已逾期状态", tenantId, overdueAssignmentIds.size());
            }

        } catch (Exception e) {
            log.error("检查并更新限时任务用户逾期状态失败，租户ID: {}", tenantId, e);
        }
    }

    /**
     * 计算任务的限时时长（毫秒）
     *
     * @param task 学习任务
     * @return 限时时长（毫秒）
     */
    private long calculateTimeLimitMillis(FtbCultivateLearnTask task) {
        Integer timeCompletionUnit = task.getTimeCompletionUnit();
        Integer timeCompletionDays = task.getTimeCompletionDays();


        if (timeCompletionUnit == 1) {
            // 小时单位：timeCompletionDays 实际表示小时数
            return timeCompletionDays.longValue() * 60 * 60 * 1000L;
        } else {
            // 天单位（默认）：timeCompletionDays 表示天数
            return timeCompletionDays.longValue() * 24 * 60 * 60 * 1000L;
        }
    }

    /**
     * 检查并更新限时任务（taskType=1）的用户逾期状态
     * 根据用户开始任务时间和任务配置的限时时长，判断是否已逾期
     *
     * @param tenantId 租户ID
     */
    private void checkAndUpdateOverdueUserTasksForTimeLimited(String tenantId) {
        try {
            Date now = new Date();

            // 查询所有限时任务(taskType=1)且状态为进行中的任务
            LambdaQueryWrapper<FtbCultivateLearnTask> taskWrapper = Wrappers.lambdaQuery();
            taskWrapper.eq(FtbCultivateLearnTask::getTaskType, 1);
            taskWrapper.eq(FtbCultivateLearnTask::getStudentTimeCompletion, 0); // 0-限时
            taskWrapper.eq(FtbCultivateLearnTask::getEnableMark, 0); // 有效
            taskWrapper.in(FtbCultivateLearnTask::getStatus, 2); // 2-进行中
            List<FtbCultivateLearnTask> timeLimitedTasks = ftbCultivateLearnTaskService.list(taskWrapper);

            if (CollUtil.isEmpty(timeLimitedTasks)) {
                return;
            }

            // 获取这些任务的ID列表
            List<String> taskIds = timeLimitedTasks.stream()
                    .map(FtbCultivateLearnTask::getId)
                    .collect(Collectors.toList());

            // 批量查询这些任务下的所有用户任务分配记录
            LambdaQueryWrapper<FtbCultivateLearnTaskAssignment> assignmentWrapper = Wrappers.lambdaQuery();
            assignmentWrapper.in(FtbCultivateLearnTaskAssignment::getTaskId, taskIds);
            assignmentWrapper.eq(FtbCultivateLearnTaskAssignment::getEnableMark, 0); // 有效
            assignmentWrapper.eq(FtbCultivateLearnTaskAssignment::getStudyStats, 1); // 0-未开始, 1-进行中
            assignmentWrapper.isNotNull(FtbCultivateLearnTaskAssignment::getLearningStartTime); // 有开始时间
            List<FtbCultivateLearnTaskAssignment> assignments = ftbCultivateLearnTaskAssignmentService.list(assignmentWrapper);

            if (CollUtil.isEmpty(assignments)) {
                return;
            }

            // 构建taskId到Task的映射
            Map<String, FtbCultivateLearnTask> taskMap = timeLimitedTasks.stream()
                    .collect(Collectors.toMap(FtbCultivateLearnTask::getId, task -> task));

            // 需要更新为逾期的用户任务ID列表
            List<String> overdueAssignmentIds = new ArrayList<>();

            for (FtbCultivateLearnTaskAssignment assignment : assignments) {
                // 计算用户应该完成的时间 = 开始学习时间 + 限时时长
                Date learningStartTime = assignment.getLearningStartTime();
                if (learningStartTime == null) {
                    continue;
                }
                FtbCultivateLearnTask task = taskMap.get(assignment.getTaskId());
                if (task == null) {
                    continue;
                }
                if (task.getTimeCompletionUnit() == null || task.getTimeCompletionUnit() < 0) {
                    continue;
                }
                if (task.getTimeCompletionDays() == null || task.getTimeCompletionDays() <= 0) {
                    continue;
                }

                // 计算任务的限时时长（毫秒）
                long timeLimitMillis = calculateTimeLimitMillis(task);
                if (timeLimitMillis <= 0) {
                    continue; // 无法计算有效限时时长，跳过
                }

                long deadlineMillis = learningStartTime.getTime() + timeLimitMillis;
                Date deadline = new Date(deadlineMillis);

                // 如果当前时间已经超过截止时间，则标记为逾期
                if (now.after(deadline)) {
                    overdueAssignmentIds.add(assignment.getId());
                }
            }

            // 批量更新逾期状态
            if (CollUtil.isNotEmpty(overdueAssignmentIds)) {
                LambdaUpdateWrapper<FtbCultivateLearnTaskAssignment> updateWrapper = Wrappers.lambdaUpdate();
                updateWrapper.set(FtbCultivateLearnTaskAssignment::getStudyStats, StudyStatsEnum.OVERDUE.getCode()); // 3-已逾期
                updateWrapper.in(FtbCultivateLearnTaskAssignment::getId, overdueAssignmentIds);
                ftbCultivateLearnTaskAssignmentService.update(updateWrapper);

                log.info("租户[{}]限时任务(taskType=1)逾期检查完成，共更新{}条用户任务为已逾期状态", tenantId, overdueAssignmentIds.size());
            }

        } catch (Exception e) {
            log.error("检查并更新限时任务(taskType=1)用户逾期状态失败，租户ID: {}", tenantId, e);
        }
    }
}
