package cn.iocoder.byzs.module.web.service.reportprogress;

import cn.iocoder.byzs.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.byzs.module.bjdx.controller.admin.coursetype.vo.CourseTypeListReqVO;
import cn.iocoder.byzs.module.bjdx.dal.dataobject.coursetype.CourseTypeDO;
import cn.iocoder.byzs.module.bjdx.dal.dataobject.reportmanage.ReportManageDO;
import cn.iocoder.byzs.module.bjdx.dal.mysql.coursetype.CourseTypeMapper;
import cn.iocoder.byzs.module.bjdx.dal.mysql.reportmanage.ReportManageMapper;
import cn.iocoder.byzs.module.web.controller.admin.course.vo.WebCourseVO;
import cn.iocoder.byzs.module.web.controller.admin.reportprogress.vo.WebReportProgressDO;
import cn.iocoder.byzs.module.web.controller.admin.reportprogress.vo.WebReportProgressDTO;
import cn.iocoder.byzs.module.web.controller.admin.reportprogress.vo.WebReportProgressVO;
import cn.iocoder.byzs.module.web.dal.mysql.reportprogress.WebReportProgressMapper;
import cn.iocoder.byzs.module.web.service.course.WebCourseServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 评估报告-课程开课率 Service 实现类
 *
 * @author lyb
 */
@Service
@Validated
public class WebReportProgressServiceImpl {

    @Resource
    private WebReportProgressMapper progressMapper;
    @Resource
    private ReportManageMapper reportManageMapper;
    @Resource
    private CourseTypeMapper courseTypeMapper;
    @Resource
    private WebCourseServiceImpl webCourseService;

    public void saveReportProgress(WebReportProgressDO progress) {

        LambdaQueryWrapperX<WebReportProgressDO> progressLambdaQueryWrapperX = new LambdaQueryWrapperX<WebReportProgressDO>()
                .eqIfPresent(WebReportProgressDO::getBrpUserId, progress.getBrpUserId())
                .eqIfPresent(WebReportProgressDO::getBrpType, progress.getBrpType())
                .eqIfPresent(WebReportProgressDO::getBrpNjId, progress.getBrpNjId());

        switch (progress.getBrpType()) {
            case "course":// 课程开课率
                progressLambdaQueryWrapperX
                        .eqIfPresent(WebReportProgressDO::getBrpCtId, progress.getBrpCtId())
                        .eqIfPresent(WebReportProgressDO::getBrpCourseId, progress.getBrpCourseId());
                WebReportProgressDO courseProgressDo = progressMapper.selectOne(progressLambdaQueryWrapperX);
                if (courseProgressDo == null) {
                    progressMapper.insert(progress);
                }else if (progress.getBrpProgress() > courseProgressDo.getBrpProgress()) {
                    courseProgressDo.setBrpProgress(progress.getBrpProgress());
                    progressMapper.updateById(courseProgressDo);
                }
                break;

            case "courseQuest":// 课程互动率
                progressLambdaQueryWrapperX
                        .eqIfPresent(WebReportProgressDO::getBrpCtId, progress.getBrpCtId())
                        .eqIfPresent(WebReportProgressDO::getBrpCourseId, progress.getBrpCourseId())
                        .eqIfPresent(WebReportProgressDO::getBrpCourseConfigId, progress.getBrpCourseConfigId());
                WebReportProgressDO courseConfigProgressDo = progressMapper.selectOne(progressLambdaQueryWrapperX);

                if (courseConfigProgressDo == null) {
                    progressMapper.insert(progress);
                }
                break;

            case "aiCount":// ai问答次数
                WebReportProgressDO aiCountProgressDo = progressMapper.selectOne(progressLambdaQueryWrapperX);

                if (aiCountProgressDo == null) {
                    progressMapper.insert(progress);
                }else {
                    aiCountProgressDo.setBrpProgress(aiCountProgressDo.getBrpProgress()+1);
                    progressMapper.updateById(aiCountProgressDo);
                }
                break;
        }
    }

    public WebReportProgressVO getReportProgress(WebReportProgressDO progress) {
        //前端数据封装
        WebReportProgressVO webReportProgressVO = new WebReportProgressVO();
        List<WebReportProgressVO.ReportProgressVo> courseProgressVoList = new ArrayList<>();
        List<WebReportProgressVO.ReportProgressVo> courseConfigProgressVoList = new ArrayList<>();

        //年级下的课程列表
        Map<String, List<Map<String, Integer>>> courseAllMap = new HashMap<>();
        List<CourseTypeDO> courseTypeDOS = courseTypeMapper.selectList(new CourseTypeListReqVO().setCtParentId(Math.toIntExact(progress.getBrpNjId())).setCtTypeNode("1"));
        courseTypeDOS.forEach(courseTypeDO -> {
            List<WebCourseVO> courseVoList = webCourseService.getCourseVoByTypeId(courseTypeDO.getId());
            List<Map<String, Integer>> courseCountMapList = new ArrayList<>();
            courseVoList.forEach(webCourseVO -> {
                Map<String, Integer> courseCountMap = new HashMap<>();
                courseCountMap.put(webCourseVO.getCourseName(), webCourseVO.getCourseConfigList().size());
                courseCountMapList.add(courseCountMap);
            });
            String sort = courseTypeDO.getCtTypeSort() > 9 ? "" : "0";
            courseAllMap.put(sort + courseTypeDO.getCtTypeSort() + " " + courseTypeDO.getCtType(), courseCountMapList);
        });

        //取进度
        List<WebReportProgressDTO> webReportProgressDOList = progressMapper.selectProgres(progress);
        Map<String, List<WebReportProgressDTO>> progressTypeMap = webReportProgressDOList.stream().collect(Collectors.groupingBy(WebReportProgressDTO::getProgressType));

        courseAllMap.forEach((kcflName, courseMap)->{
            //课程开课率
            WebReportProgressVO.ReportProgressVo courseProgressVo = new WebReportProgressVO.ReportProgressVo();
            courseProgressVo.setKcflName(kcflName);

            //课程互动率
            WebReportProgressVO.ReportProgressVo courseConfigProgressVoConfig = new WebReportProgressVO.ReportProgressVo();
            courseConfigProgressVoConfig.setKcflName(kcflName);

            //解析数据进度
            progressTypeMap.keySet().forEach(progressType -> {
                List<WebReportProgressDTO> progressDOList = progressTypeMap.get(progressType);

                switch (progressType) {
                    case "course":

                        //计算课程大纲进度
                        Map<String, List<WebReportProgressDTO>> progressKcflMap = progressDOList.stream().collect(Collectors.groupingBy(WebReportProgressDTO::getKcflName));
                            double courseSum = progressKcflMap.containsKey(kcflName) ? progressKcflMap.get(kcflName).stream().collect(Collectors.summarizingDouble(WebReportProgressDTO::getProgress)).getSum() : 0;
                        courseProgressVo.setProgress(delTwo(courseSum / courseAllMap.get(kcflName).size()));

                        break;

                    case "courseQuest":

                        //计算课程大纲进度
                        // 新增：计算courseMap所有value的总和（每个Map的value是课程配置数量）
                        int totalConfigCount = courseMap.stream()
                                .flatMap(map -> map.values().stream())  // 展开所有Map的value值
                                .mapToInt(Integer::intValue)            // 转换为int流
                                .sum();                                 // 求和
                        Map<String, List<WebReportProgressDTO>> progressKcflQuestMap = progressDOList.stream().collect(Collectors.groupingBy(WebReportProgressDTO::getKcflName));
                        double courseConfigSum = progressKcflQuestMap.containsKey(kcflName) ? progressKcflQuestMap.get(kcflName).size() : 0;
                        // 注意：这里可能需要根据实际业务调整分母（示例保持原逻辑）
                        courseConfigProgressVoConfig.setProgress(delTwo(courseConfigSum / totalConfigCount * 100));  // 调整为使用总和计算进度
                        break;

                    case "aiCount":
                        if (!progressDOList.isEmpty()) {
                            double aiCount = progressDOList.stream().collect(Collectors.summarizingDouble(WebReportProgressDTO::getProgress)).getSum();
                            webReportProgressVO.setAiCount((int) aiCount);
                        }
                        break;
                }
            });

            courseProgressVoList.add(courseProgressVo);
            courseConfigProgressVoList.add(courseConfigProgressVoConfig);  // 修正集合添加对象
        });

        // 原有总和计算逻辑（位置不变）
        double courseProgressSum = courseProgressVoList.stream().collect(Collectors.summarizingDouble(WebReportProgressVO.ReportProgressVo::getProgress)).getSum();
        double courseConfigProgressSum = courseConfigProgressVoList.stream().collect(Collectors.summarizingDouble(WebReportProgressVO.ReportProgressVo::getProgress)).getSum();
        webReportProgressVO.setNjCourseProgress(delTwo(courseProgressSum / courseProgressVoList.size()));
        webReportProgressVO.setNjCourseConfigProgress(delTwo(courseConfigProgressSum / courseConfigProgressVoList.size()));

        // 按kcflName字段排序（自然顺序）
        courseProgressVoList.sort(Comparator.comparing(WebReportProgressVO.ReportProgressVo::getKcflName));
        courseConfigProgressVoList.sort(Comparator.comparing(WebReportProgressVO.ReportProgressVo::getKcflName));
        webReportProgressVO.setReportCourseProgressList(courseProgressVoList);
        webReportProgressVO.setReportCourseConfigProgressList(courseConfigProgressVoList);

        //评语
        Double njCourseProgress = webReportProgressVO.getNjCourseProgress();
        Double njCourseConfigProgress = webReportProgressVO.getNjCourseConfigProgress();
        Integer aiCount = webReportProgressVO.getAiCount();
        List<ReportManageDO> reportManageDOList = reportManageMapper.selectList();
        StringBuffer comment = new StringBuffer();
        reportManageDOList.forEach(reportManageDO -> {
            if ((reportManageDO.getBrcReportCourseMin() <= njCourseProgress && reportManageDO.getBrcReportCourseMax() >= njCourseProgress) ||
                    (reportManageDO.getBrcReportQuestMin() <= njCourseConfigProgress && reportManageDO.getBrcReportQuestMax() >= njCourseConfigProgress) ||
                    (reportManageDO.getBrcReportAiCountMin() <= aiCount && reportManageDO.getBrcReportAiCountMax() >= aiCount)){
                comment.append(reportManageDO.getBrcReportComment());
            }
        });
        webReportProgressVO.setComment(comment.toString());
        return webReportProgressVO;
    }

    public double delTwo(Double num){
        if (Double.isInfinite(num) || Double.isNaN(num))return 0;
        BigDecimal two = new BigDecimal(num);
        double newNum = two.setScale(0, RoundingMode.HALF_UP).doubleValue();
        newNum = newNum > 100 ? 100 : newNum;
        return newNum;
    }
}