package com.xinyilu.system.service.checkreport.impl;

import com.xinyilu.common.constant.Constants;
import com.xinyilu.common.enums.ItemCodeEnums;
import com.xinyilu.system.domain.systemarea.SysArea;
import com.xinyilu.system.domain.testItemScoreinfo.TestItemScore;
import com.xinyilu.system.domain.testLevel.TestItemLevel;
import com.xinyilu.system.domain.vo.TestBodyScoreInfoVO;
import com.xinyilu.system.domain.vo.TestItemLevelScoreVO;
import com.xinyilu.system.domain.vo.childrenRanking.ChildrenRankingVO;
import com.xinyilu.system.domain.vo.childrenRanking.ItemScoreInfoVO;
import com.xinyilu.system.domain.vo.kinderPhysiqueAnalysis.StudentAndKindergartenVO;
import com.xinyilu.system.domain.vo.testActionDevelopment.TestActionDevelopmentVO;
import com.xinyilu.system.mapper.checkreport.CheckReportMapper;
import com.xinyilu.system.mapper.studentInfo.StudentInfoMapper;
import com.xinyilu.system.mapper.systemarea.SysAreaMapper;
import com.xinyilu.system.mapper.testItemScoreinfo.TestItemScoreMapper;
import com.xinyilu.system.service.checkreport.PhysicalSubstanceTestService;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

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

/**
 * @Description 身体素质测试、动作发展检测、综合体质分析报告查询方法业务层实现类
 * @Author 纪寒
 * @Date 2022-09-27 09:42:38
 * @Version 1.0
 */
@Service
public class PhysicalSubstanceTestServiceImpl implements PhysicalSubstanceTestService {

    @Resource
    private CheckReportMapper checkReportMapper;
    @Resource
    private TestItemScoreMapper testItemScoreMapper;
    @Resource
    private StudentInfoMapper studentInfoMapper;
    @Resource
    private SysAreaMapper sysAreaMapper;

    /**
     * 查询学生身体素质信息
     *
     * @param studentId 学生id
     * @param batchCode 批次编号
     * @return 身体素质信息集合
     */
    @Override
    public List<TestBodyScoreInfoVO> getPhysicalSubstanceTestInfo(Long studentId, String batchCode) {
        //查询学生测试项目成绩信息
        List<TestBodyScoreInfoVO> physicalSubstanceTestList = checkReportMapper.getPhysicalSubstanceTestInfo(studentId, batchCode);
        //批次成绩级别信息
        physicalSubstanceTestList.forEach(item -> {
            //成绩级别信息
            List<TestItemLevel> testItemLevelList = item.getTestItemLevelList();
            testItemLevelList.forEach(score -> {
                if (Objects.nonNull(item.getItemScore())
                        && Objects.nonNull(score.getLevelMinScore()) && Objects.nonNull(score.getLevelMaxScore())) {
                    if (item.getItemScore().compareTo(score.getLevelMinScore()) >= 0
                            && item.getItemScore().compareTo(score.getLevelMaxScore()) <= 0) {
                        item.setLeveName(score.getLevelName());
                    }
                }
            });
        });
        return physicalSubstanceTestList;
    }

    /**
     * 查询学生动作发展检测信息
     *
     * @param studentId 学生id
     * @param batchCode 批次编号
     * @return 动作发展检测信息集合
     */
    @Override
    public List<TestActionDevelopmentVO> getActionDevelopTestInfo(Long studentId, String batchCode) {
        // 查询这个分类中所有的项目以及项目分数
        Map<Long, List<TestActionDevelopmentVO>> listMapScore = testItemScoreMapper.selectTestNameScoreList(studentId, batchCode, ItemCodeEnums.BMI_CODE.getInfo()).stream()
                .filter(Objects::nonNull)
                .filter(itemCategoryId -> Objects.nonNull(itemCategoryId.getItemCategoryId()))
                .collect(Collectors.groupingBy(TestActionDevelopmentVO::getItemCategoryId));
        List<TestActionDevelopmentVO> itemScoreInfoList = new ArrayList<>();
        if (listMapScore.isEmpty()) {
            return itemScoreInfoList;
        }
        //组装测试分类成绩信息
        for (Map.Entry<Long, List<TestActionDevelopmentVO>> listEntry : listMapScore.entrySet()) {
            List<TestActionDevelopmentVO> listEntryValue = listEntry.getValue();
            listEntryValue.forEach(items -> items.setItemScoreAll(listEntryValue.stream().filter(item -> Objects.nonNull(item.getItemFraction()))
                    .map(TestItemScore::getItemFraction).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, BigDecimal.ROUND_HALF_UP)));
            itemScoreInfoList.addAll(listEntryValue);
        }
        return itemScoreInfoList;
    }

    /**
     * 查询学生综合体质分析信息
     *
     * @param studentId   学生id
     * @param studentName 学生姓名
     * @param batchCode   批次编号
     * @return 综合体质分析信息
     */
    @Override
    public ChildrenRankingVO getChildrenRankingTestInfo(Long studentId, String studentName, String batchCode) {
        ChildrenRankingVO childrenRankingVO = new ChildrenRankingVO();
        //计算学校排名
        calculateSchoolRank(childrenRankingVO, studentId, batchCode);
        //计算区域排名和区域占比
        calculateAreaRankAndProportion(childrenRankingVO, studentId, batchCode);
        //查询每个项目的区间信息即：纵坐标信息
        List<TestItemLevelScoreVO> itemScoreAndLevelList = studentInfoMapper.getStudentItemScoreAndLevel(studentId, batchCode);
        //横坐标信息
        childrenRankingVO.setItemStudentList(Arrays.asList(studentName, "学校平均", "全市平均"));
        //项目名称，项目成绩得分，学校平均得分，全市平均得分
        List<ItemScoreInfoVO> itemScoreList = Lists.newArrayList();
        Map<Long, TestItemLevelScoreVO> levelScoreMap = itemScoreAndLevelList.stream().filter(item -> Objects.nonNull(item.getItemId())).distinct().collect(Collectors.toMap(TestItemLevelScoreVO::getItemId, item -> item));
        levelScoreMap.forEach((itemId, levelScoreVO) -> {
            ItemScoreInfoVO scoreInfoVO = new ItemScoreInfoVO();
            scoreInfoVO.setItemId(itemId);
            scoreInfoVO.setItemName(StringUtils.isBlank(levelScoreVO.getItemName()) ? "" : levelScoreVO.getItemName());
            scoreInfoVO.setItemScore(Objects.isNull(levelScoreVO.getItemScore()) ? BigDecimal.ZERO : levelScoreVO.getItemScore());
            itemScoreList.add(scoreInfoVO);
        });
        //计算每个项目的学校平均得分，总人数
        int studentCount = studentInfoMapper.getStudentCountById(studentId);
        //查询所属幼儿园中各项目的总得分
        Map<Long, ItemScoreInfoVO> scoreMap = studentInfoMapper.getItemScoreList(studentId, batchCode).stream().filter(item -> Objects.nonNull(item.getItemId())).collect(Collectors.toMap(ItemScoreInfoVO::getItemId, item -> item));
        List<Long> sysAreaIdList = getSysAreaInfoByStudentId(studentId);
        //查询当前区域下的所有学生和幼儿园信息集合
        List<StudentAndKindergartenVO> studentKindergartenIdList = studentInfoMapper.getStudentAndKindergartenInfoByAreaIds(sysAreaIdList);
        //学生人数
        long cityStudentCount = studentKindergartenIdList.stream().filter(item -> Objects.nonNull(item.getStudentId())).map(StudentAndKindergartenVO::getStudentId).distinct().count();
        List<Long> kindergartenIdList = studentKindergartenIdList.stream().filter(item -> Objects.nonNull(item.getKindergartenId())).map(StudentAndKindergartenVO::getKindergartenId).distinct().collect(Collectors.toList());
        //查询全市平均得分
        Map<Long, ItemScoreInfoVO> cityAvgMap = studentInfoMapper.getScoreByStudentId(kindergartenIdList, batchCode).stream().filter(item -> Objects.nonNull(item.getItemId())).collect(Collectors.toMap(ItemScoreInfoVO::getItemId, item -> item));
        itemScoreList.forEach(item -> {
            //全校平均成绩
            if (!scoreMap.isEmpty()) {
                ItemScoreInfoVO scoreVO = scoreMap.getOrDefault(item.getItemId(), new ItemScoreInfoVO());
                if (Objects.nonNull(scoreVO.getItemScore()) && studentCount != 0) {
                    item.setSchoolAvgScore(scoreVO.getItemScore().divide(BigDecimal.valueOf(studentCount), 2, BigDecimal.ROUND_HALF_UP));
                } else {
                    item.setSchoolAvgScore(BigDecimal.ZERO);
                }
            } else {
                item.setSchoolAvgScore(BigDecimal.ZERO);
            }
            //全市平均成绩
            if (!cityAvgMap.isEmpty()) {
                ItemScoreInfoVO scoreVO = cityAvgMap.getOrDefault(item.getItemId(), new ItemScoreInfoVO());
                if (Objects.nonNull(scoreVO.getItemScore()) && cityStudentCount != 0) {
                    item.setCityAvgScore(scoreVO.getItemScore().divide(BigDecimal.valueOf(cityStudentCount), 2, BigDecimal.ROUND_HALF_UP));
                } else {
                    item.setCityAvgScore(BigDecimal.ZERO);
                }
            } else {
                item.setCityAvgScore(BigDecimal.ZERO);
            }
        });
        childrenRankingVO.setItemScoreList(itemScoreList);
        return childrenRankingVO;
    }

    /**
     * 计算学校排名
     *
     * @param childrenRankingVO 返回值参数
     * @param studentId         学生id
     * @param batchCode         批次编号
     */
    private void calculateSchoolRank(ChildrenRankingVO childrenRankingVO, Long studentId, String batchCode) {
        //计算学校排名
        List<ChildrenRankingVO> scoreList = studentInfoMapper.getStudentItemScore(studentId, batchCode)
                .stream().filter(item -> Objects.nonNull(item.getStudentId()) || Objects.nonNull(item.getItemScore()))
                .sorted(Comparator.comparing(ChildrenRankingVO::getItemScore).reversed()).collect(Collectors.toList());
        int schoolRank = 0;
        for (int i = 1; i <= scoreList.size(); i++) {
            if (studentId.equals(scoreList.get(i - 1).getStudentId())) {
                schoolRank = i;
            }
        }
        childrenRankingVO.setSchoolRank(schoolRank);
    }

    /**
     * 计算区域排名和区域占比
     *
     * @param childrenRankingVO 返回值参数
     * @param studentId         学生id
     * @param batchCode         批次编号
     */
    private void calculateAreaRankAndProportion(ChildrenRankingVO childrenRankingVO, Long studentId, String batchCode) {
        //查询区域内所有的学校
        List<Long> kindergartenInfoList = studentInfoMapper.getKindergartenInfoList(studentId, Constants.REGION_LEVEL);
        //去查询这些学校下所有的学生的信息
        List<ChildrenRankingVO> studentItemScoreByKindList = studentInfoMapper.getStudentItemScoreBykindList(kindergartenInfoList, batchCode)
                .stream().filter(item -> Objects.nonNull(item.getStudentId()) || Objects.nonNull(item.getItemScore()))
                .sorted(Comparator.comparing(ChildrenRankingVO::getItemScore).reversed()).collect(Collectors.toList());
        int areaRank = 0;
        for (int i = 1; i <= studentItemScoreByKindList.size(); i++) {
            if (studentId.equals(studentItemScoreByKindList.get(i - 1).getStudentId())) {
                areaRank = i;
            }
        }
        childrenRankingVO.setAreaRank(areaRank);
        //区域成绩占比
        int areaStudentCount = studentItemScoreByKindList.size();
        if (areaStudentCount > 0) {
            childrenRankingVO.setAreaProportion(BigDecimal.valueOf(areaRank).divide(BigDecimal.valueOf(areaStudentCount), 2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)) + "%");
        } else {
            childrenRankingVO.setAreaProportion("0%");
        }
    }

    /**
     * 根据学生id查询对应得区域信息
     *
     * @param studentId 学生id
     * @return 区域信息集合
     */
    private List<Long> getSysAreaInfoByStudentId(Long studentId) {
        SysArea sysArea = studentInfoMapper.getSysAreaByStudentId(studentId);
        List<Long> sysAreaIdList = Lists.newArrayList();
        if (Objects.nonNull(sysArea.getLevel())) {
            //所属市
            if (Constants.CITY_LEVEL.equals(sysArea.getLevel())) {
                sysAreaIdList = sysAreaMapper.getSysAreaIdList(Objects.isNull(sysArea.getId()) ? 0L : sysArea.getId());
            }
            //所属区
            if (Constants.REGION_LEVEL.equals(sysArea.getLevel())) {
                sysAreaIdList = sysAreaMapper.getSysAreaIdList(Objects.isNull(sysArea.getParentId()) ? 0L : sysArea.getParentId());
            }
        }
        return sysAreaIdList;
    }
}
