package com.qmth.distributed.print.business.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qmth.distributed.print.business.bean.dto.CourseWeightDto;
import com.qmth.distributed.print.business.bean.dto.obe.CourseRequirementMatrixDto;
import com.qmth.distributed.print.business.bean.dto.obe.MatrixRequirementDto;
import com.qmth.distributed.print.business.bean.dto.obe.MatrixSubRequirementDto;
import com.qmth.distributed.print.business.bean.dto.report.*;
import com.qmth.distributed.print.business.bean.result.ObeCourseRequirementListResult;
import com.qmth.distributed.print.business.bean.result.ObeCourseWeightResult;
import com.qmth.distributed.print.business.entity.ObeCourseRequirementReport;
import com.qmth.distributed.print.business.entity.TRBasicInfo;
import com.qmth.distributed.print.business.mapper.ObeCourseRequirementReportMapper;
import com.qmth.distributed.print.business.service.ObeCourseRequirementReportService;
import com.qmth.distributed.print.business.service.TRBasicInfoService;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.util.JacksonUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 课程毕业要求报表 服务实现类
 * </p>
 *
 * @author wangliang
 * @since 2024-06-13
 */
@Service
public class ObeCourseRequirementReportServiceImpl extends ServiceImpl<ObeCourseRequirementReportMapper, ObeCourseRequirementReport> implements ObeCourseRequirementReportService {
    private final static Logger log = LoggerFactory.getLogger(ObeCourseRequirementReportServiceImpl.class);

    @Resource
    TRBasicInfoService trBasicInfoService;

    @Resource
    ObeCourseRequirementReportService obeCourseRequirementReportService;

    /**
     * 换算课程毕业达成度报表详情
     *
     * @param courseRequirementMatrixDtoList
     * @param obeCourseOutlineId
     * @param examId
     * @return
     */
    @Override
    public Map<String, Object> matrixCourseReportInfo(List<CourseRequirementMatrixDto> courseRequirementMatrixDtoList, Long obeCourseOutlineId, Long examId) {
        Map<String, Object> resultMap = new HashMap<>();
        List<ObeCourseRequirementDto> obeCourseRequirementDtoList = new ArrayList<>();
        Map<Long, List<ObeSubRequirementsDto>> obeSubRequirementsDtoMap = new LinkedHashMap<>();
        if (!CollectionUtils.isEmpty(courseRequirementMatrixDtoList)) {
            ObeCourseWeightResult obeCourseWeightResult = trBasicInfoService.findCourseWeightResultRmi(obeCourseOutlineId);
            String s1 = "{\"weightSettingSign\":\"531143129521197056\",\"dimensionSign\":\"511110362758647808\",\"submitForm\":[{\"courseTargetId\":\"511110308371107840\",\"courseTargetName\":\"课程目标1\",\"obeCultureProgramRequirementId\":533285303218077696,\"obeCultureProgramRequirementName\":\"1-1\",\"dimensionList\":[{\"id\":\"511110237860663297\",\"code\":\"A1\",\"name\":\"第一节 映射与函数\"}],\"dimensionStr\":\"第一节 映射与函数(A1)\",\"degreeRequirement\":\"课程目标1\",\"totalWeight\":40,\"evaluationList\":[{\"evaluationId\":\"511110589855043584\",\"evaluationName\":\"评价方式2\",\"evaluationDesc\":\"评价方式2\",\"enable\":true,\"weight\":10,\"targetScore\":100,\"evaluationType\":\"CUSTOM\"},{\"evaluationId\":\"511110641155575808\",\"evaluationName\":\"评价方式1\",\"evaluationDesc\":\"评价方式1\",\"enable\":true,\"weight\":10,\"targetScore\":100,\"evaluationType\":\"CUSTOM\"},{\"evaluationId\":\"511110668787650560\",\"evaluationName\":\"评价方式3\",\"evaluationDesc\":\"评价方式3\",\"enable\":false,\"weight\":null,\"targetScore\":0,\"evaluationType\":\"CUSTOM\"},{\"evaluationId\":\"511110692196061184\",\"evaluationName\":\"评价方式4\",\"evaluationDesc\":\"评价方式14\",\"enable\":false,\"weight\":null,\"targetScore\":0,\"evaluationType\":\"CUSTOM\"},{\"evaluationId\":\"510826411045425152\",\"evaluationName\":\"期末考试\",\"evaluationDesc\":\"按阅卷功能模块里的卷面成绩计算\",\"enable\":true,\"weight\":20,\"targetScore\":50,\"evaluationType\":\"DEFAULT\"}]},{\"courseTargetId\":\"511110362817368064\",\"courseTargetName\":\"课程目标2\",\"obeCultureProgramRequirementId\":533285303218077697,\"obeCultureProgramRequirementName\":\"2-1\",\"dimensionList\":[{\"id\":\"511110237860663299\",\"code\":\"B1\",\"name\":\"第二节 数列的极限\"}],\"dimensionStr\":\"第二节 数列的极限(B1)\",\"degreeRequirement\":\"课程目标2\",\"totalWeight\":60,\"evaluationList\":[{\"evaluationId\":\"511110589855043584\",\"evaluationName\":\"评价方式2\",\"evaluationDesc\":\"评价方式2\",\"enable\":false,\"weight\":null,\"targetScore\":0,\"evaluationType\":\"CUSTOM\"},{\"evaluationId\":\"511110641155575808\",\"evaluationName\":\"评价方式1\",\"evaluationDesc\":\"评价方式1\",\"enable\":false,\"weight\":null,\"targetScore\":0,\"evaluationType\":\"CUSTOM\"},{\"evaluationId\":\"511110668787650560\",\"evaluationName\":\"评价方式3\",\"evaluationDesc\":\"评价方式3\",\"enable\":true,\"weight\":40,\"targetScore\":100,\"evaluationType\":\"CUSTOM\"},{\"evaluationId\":\"510826411045425152\",\"evaluationName\":\"期末考试\",\"evaluationDesc\":\"按阅卷功能模块里的卷面成绩计算\",\"enable\":true,\"weight\":20,\"targetScore\":50,\"evaluationType\":\"DEFAULT\"}]}]}";
            obeCourseWeightResult = JSONObject.parseObject(s1, ObeCourseWeightResult.class);
            log.info("obeCourseWeightResult:{}", JacksonUtil.parseJson(obeCourseWeightResult));

            List<CourseWeightDto> courseWeightDtoList = obeCourseWeightResult.getSubmitForm();
            //课程目标指标点集合map
            Map<Long, CourseWeightDto> cultureProgramRequirementIdMap = courseWeightDtoList.stream().collect(Collectors.toMap(CourseWeightDto::getObeCultureProgramRequirementId, Function.identity(), (dto1, dto2) -> dto1));
            Map<Long, List<ObeSubRequirementsDto>> matrixSubRequirementIdMap = new HashMap<>();//课程目标指标点集合-多个目标共用一个指标点
            Map<Long, CourseTargetWebDto> courseTargetWebDtoMap = new HashMap<>();//课程目标集合
            for (CourseRequirementMatrixDto c : courseRequirementMatrixDtoList) {
                ObeCourseRequirementDto obeCourseRequirementDto = new ObeCourseRequirementDto(c);
                obeCourseRequirementDtoList.add(obeCourseRequirementDto);
                TRBasicInfo trBasicInfo = trBasicInfoService.queryBasicInfo(examId, c.getCourseCode(), null, 510826410978316288L);
                if (Objects.nonNull(trBasicInfo)) {
                    ReportCourseEvaluationResultDto reportCourseEvaluationResultDto = Objects.nonNull(trBasicInfo.getCourseEvaluationResult()) ? JSONObject.parseObject(trBasicInfo.getCourseEvaluationResult(), ReportCourseEvaluationResultDto.class) : null;
                    if (Objects.nonNull(reportCourseEvaluationResultDto)) {
                        List<CourseTargetWebDto> courseTargetWebDtoList = reportCourseEvaluationResultDto.getTargetList();
                        courseTargetWebDtoMap = courseTargetWebDtoList.stream().collect(Collectors.toMap(CourseTargetWebDto::getTargetId, Function.identity(), (dto1, dto2) -> dto1));
                    }
                }
                List<MatrixRequirementDto> matrixRequirementDtoList = c.getRequirements();
                if (!CollectionUtils.isEmpty(matrixRequirementDtoList)) {
                    List<ObeRequirementDto> obeRequirementDtoList = new ArrayList<>();
                    obeCourseRequirementDto.setObeRequirements(obeRequirementDtoList);
                    for (MatrixRequirementDto matrixRequirementDto : matrixRequirementDtoList) {
                        ObeRequirementDto obeRequirementDto = new ObeRequirementDto(matrixRequirementDto);
                        obeRequirementDtoList.add(obeRequirementDto);
                        List<MatrixSubRequirementDto> matrixSubRequirementDtoList = matrixRequirementDto.getSubRequirements();
                        if (!CollectionUtils.isEmpty(matrixSubRequirementDtoList)) {
                            List<ObeSubRequirementsDto> obeSubRequirementsDtoList = new ArrayList<>();
                            obeRequirementDto.setObeSubRequirements(obeSubRequirementsDtoList);
                            for (MatrixSubRequirementDto matrixSubRequirementDto : matrixSubRequirementDtoList) {
                                ObeSubRequirementsDto obeSubRequirementsDto = new ObeSubRequirementsDto(matrixSubRequirementDto);
                                obeSubRequirementsDtoList.add(obeSubRequirementsDto);
                                if (Objects.nonNull(matrixSubRequirementDto.getScale())) {
                                    //多个课程目标关联同一个指标点
                                    if (matrixSubRequirementIdMap.containsKey(matrixSubRequirementDto.getId())) {
                                        List<ObeSubRequirementsDto> obeRequirementsDtoList = matrixSubRequirementIdMap.get(matrixSubRequirementDto.getId());
                                        Map<Long, CourseTargetWebDto> map = obeRequirementsDtoList.stream().collect(Collectors.toMap(ObeSubRequirementsDto::getTargetId, Function.identity(), (dto1, dto2) -> dto1));
                                        CourseWeightDto courseWeightDto = cultureProgramRequirementIdMap.get(matrixSubRequirementDto.getId());
                                        if (Objects.nonNull(courseWeightDto)) {
                                            CourseTargetWebDto courseTargetWebDto = courseTargetWebDtoMap.get(courseWeightDto.getCourseTargetId());
                                            if (!map.containsKey(courseTargetWebDto.getTargetId())) {
                                                obeRequirementsDtoList.add(new ObeSubRequirementsDto(courseTargetWebDto, matrixSubRequirementDto));
                                            }
                                        }
                                        matrixSubRequirementIdMap.put(matrixSubRequirementDto.getId(), obeRequirementsDtoList);
                                    } else {
                                        CourseWeightDto courseWeightDto = cultureProgramRequirementIdMap.get(matrixSubRequirementDto.getId());
                                        if (Objects.nonNull(courseWeightDto)) {
                                            CourseTargetWebDto courseTargetWebDto = courseTargetWebDtoMap.get(courseWeightDto.getCourseTargetId());
                                            matrixSubRequirementIdMap.put(matrixSubRequirementDto.getId(), new ArrayList<>(Arrays.asList(new ObeSubRequirementsDto(courseTargetWebDto, matrixSubRequirementDto))));
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                //计算各个课程的指标点达成值
                if (!CollectionUtils.isEmpty(matrixSubRequirementIdMap)) {
                    for (Map.Entry<Long, List<ObeSubRequirementsDto>> entry : matrixSubRequirementIdMap.entrySet()) {
                        Double evaluationValue = entry.getValue().stream().mapToDouble(x -> x.getEvaluationValue().doubleValue()).average().orElse(0.0d);
                        ObeSubRequirementsDto obeSubRequirementsDto = entry.getValue().get(0);
                        BigDecimal bigDecimal = new BigDecimal(evaluationValue).multiply(new BigDecimal(obeSubRequirementsDto.getScale())).setScale(2, BigDecimal.ROUND_HALF_UP);
                        entry.getValue().stream().peek(x -> x.setMatrixDegree(bigDecimal)).collect(Collectors.toList());
                    }
                }
                //计算各个课程的指标点达成值
                List<ObeRequirementDto> obeRequirementDtoList = obeCourseRequirementDto.getObeRequirements();
                if (!CollectionUtils.isEmpty(obeRequirementDtoList)) {
                    for (ObeRequirementDto o : obeRequirementDtoList) {
                        List<ObeSubRequirementsDto> obeSubRequirementsDtoList = o.getObeSubRequirements();
                        for (ObeSubRequirementsDto obeSubRequirementsDto : obeSubRequirementsDtoList) {
                            if (matrixSubRequirementIdMap.containsKey(obeSubRequirementsDto.getId())) {
                                obeSubRequirementsDto.setMatrixDegree(matrixSubRequirementIdMap.get(obeSubRequirementsDto.getId()).get(0).getMatrixDegree());
                            }
                            if (obeSubRequirementsDtoMap.containsKey(obeSubRequirementsDto.getId())) {
                                List<ObeSubRequirementsDto> obeSubRequirementsDtoListTemp = obeSubRequirementsDtoMap.get(obeSubRequirementsDto.getId());
                                obeSubRequirementsDtoListTemp.add(obeSubRequirementsDto);
                                obeSubRequirementsDtoMap.put(obeSubRequirementsDto.getId(), obeSubRequirementsDtoListTemp);
                            } else {
                                obeSubRequirementsDtoMap.put(obeSubRequirementsDto.getId(), new ArrayList<>(Arrays.asList(obeSubRequirementsDto)));
                            }
                        }
                    }
                }
            }
        }
        resultMap.put(SystemConstant.OBE_COURSE_REQUIREMENT_DTO_LIST, obeCourseRequirementDtoList);
        resultMap.put(SystemConstant.OBE_SUB_REQUIREMENT_DTO_MAP, obeSubRequirementsDtoMap);
        return resultMap;
    }

    /**
     * 换算课程毕业达成度报表
     *
     * @param obeCourseRequirementDtoList
     * @param obeSubRequirementsDtoMap
     * @return
     */
    @Override
    public ObeCourseRequirementDto matrixCourseReport(List<ObeCourseRequirementDto> obeCourseRequirementDtoList, Map<Long, List<ObeSubRequirementsDto>> obeSubRequirementsDtoMap) {
        //计算指标和毕业达成度
        ObeCourseRequirementDto obeCourseRequirementResultDto = new ObeCourseRequirementDto();
        if (!CollectionUtils.isEmpty(obeCourseRequirementDtoList)) {
            obeCourseRequirementDtoList = this.matrixCourseReportCommon(obeCourseRequirementDtoList, obeSubRequirementsDtoMap);
            obeCourseRequirementResultDto = obeCourseRequirementDtoList.get(obeCourseRequirementDtoList.size() - 1);
            obeCourseRequirementResultDto.updateInfo();
        }
        return obeCourseRequirementResultDto;
    }

    /**
     * 换算课程毕业达成度报表共用
     *
     * @param obeCourseRequirementDtoList
     * @param obeSubRequirementsDtoMap
     * @return
     */
    @Override
    public List<ObeCourseRequirementDto> matrixCourseReportCommon(List<ObeCourseRequirementDto> obeCourseRequirementDtoList, Map<Long, List<ObeSubRequirementsDto>> obeSubRequirementsDtoMap) {
        for (ObeCourseRequirementDto o : obeCourseRequirementDtoList) {
            List<ObeRequirementDto> obeRequirementDtoList = o.getObeRequirements();
            for (ObeRequirementDto obeRequirementDto : obeRequirementDtoList) {
                List<ObeSubRequirementsDto> obeSubRequirementsDtoList = obeRequirementDto.getObeSubRequirements();
                for (ObeSubRequirementsDto obeSubRequirementsDto : obeSubRequirementsDtoList) {
                    if (obeSubRequirementsDtoMap.containsKey(obeSubRequirementsDto.getId())) {
                        Double degree = obeSubRequirementsDtoMap.get(obeSubRequirementsDto.getId()).stream().mapToDouble(x -> x.getMatrixDegree().doubleValue()).sum();
                        obeRequirementDto.setMatrixDegree(new BigDecimal(degree).setScale(2, BigDecimal.ROUND_HALF_UP));
                    }
                }
                Double degree = obeRequirementDtoList.stream().filter(x -> x.getMatrixDegree().doubleValue() > 0).mapToDouble(x -> x.getMatrixDegree().doubleValue()).min().orElse(0.0d);
                o.setMatrixDegree(new BigDecimal(degree).setScale(2, BigDecimal.ROUND_HALF_UP));
            }
        }
        return obeCourseRequirementDtoList;
    }

    /**
     * 查找课程毕业达成度报表列表
     *
     * @param iPage
     * @param professionalId
     * @param cultureProgramName
     * @return
     */
    @Override
    public IPage<ObeCourseRequirementListResult> obeCourseRequirementReportList(IPage<Map> iPage, Long professionalId, String cultureProgramName) {
        return this.baseMapper.obeCourseRequirementReportList(iPage, professionalId, cultureProgramName);
    }

    /**
     * 根据培养方案和课程老师id删除报表
     *
     * @param cultureProgramId
     * @return
     */
    @Override
    @Transactional
    public boolean removeReport(Long cultureProgramId) {
        ObeCourseRequirementReport obeCourseRequirementReport = obeCourseRequirementReportService.findByCultureProgramId(cultureProgramId);
        return Objects.nonNull(obeCourseRequirementReport) ? obeCourseRequirementReportService.removeById(obeCourseRequirementReport.getId()) : false;
    }

    /**
     * 根据培养方案和课程老师id查询报表
     *
     * @param cultureProgramId
     * @return
     */
    @Override
    public ObeCourseRequirementReport findByCultureProgramId(Long cultureProgramId) {
        return obeCourseRequirementReportService.getOne(new QueryWrapper<ObeCourseRequirementReport>().lambda().eq(ObeCourseRequirementReport::getCultureProgramId, cultureProgramId));
    }
}
