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

import com.xinyilu.common.core.domain.AjaxResult;
import com.xinyilu.common.enums.CategoryLevelEnum;
import com.xinyilu.common.enums.ItemCodeEnums;
import com.xinyilu.common.utils.AgeUtil;
import com.xinyilu.system.domain.testLevel.TestItemLevel;
import com.xinyilu.system.domain.vo.physiqueAnalysis.PhysiqueAnalysisVO;
import com.xinyilu.system.domain.vo.physiqueAnalysis.PhysiqueCategoryVO;
import com.xinyilu.system.mapper.studentInfo.StudentInfoMapper;
import com.xinyilu.system.service.physiqueAnalysis.PhysiqueAnalysisService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
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.util.*;
import java.util.stream.Collectors;

/**
 * @Description 体质综合分析业务层实现类
 * @Author 纪寒
 * @Date 2022-08-11 09:25:22
 * @Version 1.0
 */
@Slf4j
@Service
public class PhysiqueAnalysisServiceImpl implements PhysiqueAnalysisService {

    @Resource
    private StudentInfoMapper studentInfoMapper;

    /**
     * 根据学生id和批次编号统计学生体质综合分析数据
     *
     * @param studentId 学生id
     * @param batchCode 批次编码
     * @return 分析数据结果
     * @throws Exception 异常信息
     */
    @Override
    public AjaxResult getPhysiqueAnalysisInfo(Long studentId, String batchCode) throws Exception {
        //查询学生相关信息
        PhysiqueAnalysisVO physiqueAnalysisVO = studentInfoMapper.getStudentInfoById(studentId);
        if (Objects.isNull(physiqueAnalysisVO)) {
            return AjaxResult.error("学生信息不存在");
        }
        //计算学生年龄
        if (Objects.nonNull(physiqueAnalysisVO.getBirthDate())) {
            physiqueAnalysisVO.setStudentAge(AgeUtil.getStudentAgeMonth(physiqueAnalysisVO.getBirthDate().toString()));
        }
        //统计一级项目分类的得分，以及一级分类的总得分
        List<PhysiqueCategoryVO> firstItemCategoryList = studentInfoMapper.getFirstItemCategory(studentId, CategoryLevelEnum.FIRST_LEVEL.getLevelId(), batchCode, ItemCodeEnums.BMI_CODE.getInfo());
        if (CollectionUtils.isEmpty(firstItemCategoryList)) {
            return AjaxResult.success();
        }
        //一级分类总成绩
        physiqueAnalysisVO.setTotalCategoryScore(firstItemCategoryList.stream()
                .filter(item -> Objects.nonNull(item.getCategoryScore()))
                .map(PhysiqueCategoryVO::getCategoryScore)
                .reduce(BigDecimal.ZERO, BigDecimal::add));
        //筛选出单个成绩 获取每个分类的成绩的和
        List<PhysiqueCategoryVO> physiqueCategoryVOList = new ArrayList<>();
        Map<Long, List<PhysiqueCategoryVO>> physiqueCategoryMap = firstItemCategoryList.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getId())).collect(Collectors.groupingBy(PhysiqueCategoryVO::getId));
        physiqueCategoryMap.forEach((id, physiqueCategory) -> {
            PhysiqueCategoryVO physiqueCategoryVO = new PhysiqueCategoryVO();
            physiqueCategoryVO.setId(Objects.isNull(id) ? null : id);
            physiqueCategoryVO.setCategoryName(StringUtils.isBlank(physiqueCategory.get(0).getCategoryName()) ? "" : physiqueCategory.get(0).getCategoryName());
            BigDecimal bigDecimal = physiqueCategory.stream().filter(item -> Objects.nonNull(item.getCategoryScore()))
                    .map(PhysiqueCategoryVO::getCategoryScore)
                    .reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, BigDecimal.ROUND_HALF_UP);
            if (Objects.nonNull(bigDecimal)){
                physiqueCategoryVO.setCategoryScore(bigDecimal);
            }
            physiqueCategoryVOList.add(physiqueCategoryVO);
        });
        physiqueAnalysisVO.setFirstItemCategoryList(physiqueCategoryVOList);
        //统计每个学生项目成绩所属分类的得分信息
        List<PhysiqueCategoryVO> itemCategoryScoreList = studentInfoMapper.getItemCategoryScore(studentId, batchCode, ItemCodeEnums.BMI_CODE.getInfo());
        if (CollectionUtils.isEmpty(itemCategoryScoreList)) {
            return AjaxResult.success(physiqueAnalysisVO);
        }
        //徽章集合即：分类缩写名称集合
        List<String> categoryNameList = itemCategoryScoreList.stream().filter(item -> StringUtils.isNotBlank(item.getCategoryNameAbbreviate())).map(PhysiqueCategoryVO::getCategoryNameAbbreviate).collect(Collectors.toList());
        physiqueAnalysisVO.setCategoryNameList(categoryNameList);
        //分类id集合
        List<Long> categoryIdList = itemCategoryScoreList.stream().filter(item -> Objects.nonNull(item.getId())).map(PhysiqueCategoryVO::getId).collect(Collectors.toList());
        //根据分类id查询各分类得分区间信息
        Map<Long, List<TestItemLevel>> levelMap = studentInfoMapper.getTestItemLevelByCategoryId(categoryIdList).stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getItemCategoryId())).collect(Collectors.groupingBy(TestItemLevel::getItemCategoryId));
        if (levelMap.isEmpty()) {
            physiqueAnalysisVO.setPhysiqueCategoryList(itemCategoryScoreList);
            return AjaxResult.success(physiqueAnalysisVO);
        }
        itemCategoryScoreList.forEach(item -> {
            List<TestItemLevel> levelList = levelMap.getOrDefault(item.getId(), Lists.newArrayList());
            levelList.forEach(level -> {
                if (Objects.nonNull(item.getCategoryScore()) && Objects.nonNull(level.getLevelMinScore())
                        && Objects.nonNull(level.getLevelMaxScore())) {
                    if (item.getCategoryScore().compareTo(level.getLevelMinScore()) >= 0
                            && item.getCategoryScore().compareTo(level.getLevelMaxScore()) <= 0) {
                        item.setLevelName(StringUtils.isBlank(level.getLevelName()) ? "" : level.getLevelName());
                    }
                }
            });
            //获取区间最大值
            List<BigDecimal> maxScoreList = levelList.stream().filter(score -> Objects.nonNull(score.getLevelMaxScore())).map(TestItemLevel::getLevelMaxScore).collect(Collectors.toList());
            BigDecimal max = BigDecimal.ZERO;
            if (CollectionUtils.isNotEmpty(maxScoreList)) {
                max = Collections.max(maxScoreList);
            }
            item.setMaxScore(max);
        });
        physiqueAnalysisVO.setPhysiqueCategoryList(itemCategoryScoreList);
        return AjaxResult.success(physiqueAnalysisVO);
    }
}
