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

import com.xinyilu.common.core.domain.AjaxResult;
import com.xinyilu.common.core.domain.entity.SysDictData;
import com.xinyilu.common.enums.ItemCodeEnums;
import com.xinyilu.common.enums.ItemFlagEnum;
import com.xinyilu.common.enums.StudentAgeFlagEnum;
import com.xinyilu.common.utils.AgeUtil;
import com.xinyilu.system.domain.heightWeightInfo.HeightWeightInfo;
import com.xinyilu.system.domain.testLevel.TestItemLevel;
import com.xinyilu.system.domain.vo.BodyShapeAnalysisVO;
import com.xinyilu.system.domain.vo.BodyShapeItemScoreVO;
import com.xinyilu.system.domain.vo.StudentInfoVO;
import com.xinyilu.system.mapper.SysDictDataMapper;
import com.xinyilu.system.mapper.heightWeightInfo.HeightWeightInfoMapper;
import com.xinyilu.system.mapper.studentInfo.StudentInfoMapper;
import com.xinyilu.system.mapper.testItem.TestItemsMapper;
import com.xinyilu.system.service.bodyShape.BodyShapeService;
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.time.LocalDate;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Description 身体形态测试业务层实现类
 * @Author 纪寒
 * @Date 2022-08-10 10:02:54
 */
@Service
@Slf4j
public class BodyShapeServiceImpl implements BodyShapeService {

    /**
     * 一岁年龄标识
     */
    private static final Double ONE_YEAR = 1.0;

    @Resource
    private SysDictDataMapper sysDictDataMapper;
    @Resource
    private TestItemsMapper testItemsMapper;
    @Resource
    private StudentInfoMapper studentInfoMapper;
    @Resource
    private HeightWeightInfoMapper heightWeightInfoMapper;

    /**
     * 根据学习id查询学生身体形态测试数据分析
     *
     * @param studentId 学生id
     * @param batchCode 批次编号
     * @return 学生分析结果
     * @throws Exception 异常信息
     */
    @Override
    public AjaxResult getBodyShapeAnalysis(Long studentId, String batchCode) throws Exception {
        //查询学生个人信息
        StudentInfoVO studentInfoVO = studentInfoMapper.selectStudentInfoById(studentId);
        if (Objects.isNull(studentInfoVO)) {
            return AjaxResult.error("该学生信息不存在");
        }
        BodyShapeAnalysisVO analysisVO = new BodyShapeAnalysisVO();
        analysisVO.setStudentName(studentInfoVO.getStudentName());
        //查询身体形态标题和身体形态描述信息
        List<SysDictData> bodyShapeDict = sysDictDataMapper.selectDictDataByType("body_shape_test");
        if (CollectionUtils.isEmpty(bodyShapeDict)) {
            return AjaxResult.success();
        }
        analysisVO.setShapeTitle(StringUtils.isBlank(bodyShapeDict.get(0).getDictLabel()) ? "" : bodyShapeDict.get(0).getDictLabel());
        analysisVO.setShapeDescription(StringUtils.isBlank(bodyShapeDict.get(0).getRemark()) ? "" : bodyShapeDict.get(0).getRemark());
        //获取身高和体重项目编号
        List<String> itemCodeList = Lists.newArrayList();
        itemCodeList.add(ItemCodeEnums.HEIGHT_CODE.getInfo());
        itemCodeList.add(ItemCodeEnums.WEIGHT_CODE.getInfo());
        //查询身高项目和体重项目的成绩信息
        List<BodyShapeItemScoreVO> itemScoreList = testItemsMapper.getBodyShapeScoreInfo(studentId, itemCodeList, batchCode);
        Map<String, BodyShapeItemScoreVO> itemCodeMap = itemScoreList.stream().filter(Objects::nonNull)
                .filter(item -> StringUtils.isNotBlank(item.getItemCode()))
                .collect(Collectors.toMap(BodyShapeItemScoreVO::getItemCode, item -> item));
        BigDecimal heightScore = BigDecimal.ZERO;
        BigDecimal weightScore = BigDecimal.ZERO;
        BigDecimal bmiScore = BigDecimal.ZERO;
        if (!itemCodeMap.isEmpty()) {
            //获取身高项目信息
            BodyShapeItemScoreVO heightInfo = itemCodeMap.getOrDefault(ItemCodeEnums.HEIGHT_CODE.getInfo(), new BodyShapeItemScoreVO());
            analysisVO.setHeightName(StringUtils.isEmpty(heightInfo.getItemName()) ? "" : heightInfo.getItemName());
            analysisVO.setHeightMeasureUnit(StringUtils.isEmpty(heightInfo.getMeasureUnit()) ? "" : heightInfo.getMeasureUnit());
            heightScore = Objects.isNull(heightInfo.getItemScore()) ? BigDecimal.ZERO : heightInfo.getItemScore();
            analysisVO.setHeightScore(heightScore);
            //获取体重信息
            BodyShapeItemScoreVO weightInfo = itemCodeMap.getOrDefault(ItemCodeEnums.WEIGHT_CODE.getInfo(), new BodyShapeItemScoreVO());
            analysisVO.setWeightName(StringUtils.isEmpty(weightInfo.getItemName()) ? "" : weightInfo.getItemName());
            analysisVO.setWeightMeasureUnit(StringUtils.isEmpty(weightInfo.getMeasureUnit()) ? "" : weightInfo.getMeasureUnit());
            weightScore = Objects.isNull(weightInfo.getItemScore()) ? BigDecimal.ZERO : weightInfo.getItemScore();
            analysisVO.setWeightScore(weightScore);
            //计算BMI，BMI = 体重 / 身高的平方
            BigDecimal squareHeight = heightScore.multiply(heightScore).divide(BigDecimal.valueOf(100), 2, BigDecimal.ROUND_HALF_UP);
            if (Objects.nonNull(squareHeight) && squareHeight.compareTo(BigDecimal.ZERO) != 0) {
                bmiScore = weightScore.divide(squareHeight, 4, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100)).setScale(2, BigDecimal.ROUND_HALF_UP);
                analysisVO.setBmi(bmiScore);
            } else {
                analysisVO.setBmi(BigDecimal.ZERO);
            }
        }
        //计算年龄身高比和体重身高比信息
        this.getHeightAndWeightInfo(studentInfoVO, analysisVO, heightScore, weightScore);
        //查询BMI项目成绩信息
        this.getBmiItemInfo(analysisVO, ItemCodeEnums.BMI_CODE.getInfo(), bmiScore);
        return AjaxResult.success(analysisVO);
    }

    /**
     * 查询年龄身高比信息和体重身高比信息
     *
     * @param studentInfoVO 学生信息
     * @param analysisVO    返回值信息
     * @param heightScore   身高成绩
     * @param weightScore   体重成绩
     * @throws Exception 异常信息
     */
    private void getHeightAndWeightInfo(StudentInfoVO studentInfoVO, BodyShapeAnalysisVO analysisVO,
                                        BigDecimal heightScore, BigDecimal weightScore) throws Exception {
        //根据出生日期计算学生的年龄，支持到年即：几岁，不支持几个月
        double studentAge = AgeUtil.getStudentAgeMonth(Objects.isNull(studentInfoVO.getBirthDate()) ? LocalDate.now().toString() : studentInfoVO.getBirthDate().toString());
        HeightWeightInfo heightWeightInfo = new HeightWeightInfo();
        if (ONE_YEAR.equals(studentAge)) {
            //一岁表中存的是12个月，作特殊处理
            heightWeightInfo.setAge(BigDecimal.valueOf(12));
            heightWeightInfo.setMonthAgeFlag(StudentAgeFlagEnum.MONTH.getInfo());
        } else {
            heightWeightInfo.setAge(BigDecimal.valueOf(studentAge));
            heightWeightInfo.setMonthAgeFlag(StudentAgeFlagEnum.YEAR.getInfo());
        }
        heightWeightInfo.setSex(StringUtils.isEmpty(studentInfoVO.getStudentSex()) ? "" : studentInfoVO.getStudentSex());
        List<HeightWeightInfo> heightWeightInfoList = heightWeightInfoMapper.selectHeightWeightInfoList(heightWeightInfo);
        Map<String, HeightWeightInfo> weightInfoMap = heightWeightInfoList.stream().filter(Objects::nonNull)
                .filter(item -> StringUtils.isNotBlank(item.getItemFlag()))
                .collect(Collectors.toMap(HeightWeightInfo::getItemFlag, item -> item));
        if (!weightInfoMap.isEmpty()) {
            //年龄身高比信息
            HeightWeightInfo heightAgeInfo = weightInfoMap.getOrDefault(ItemFlagEnum.HEIGHT.getInfo(), new HeightWeightInfo());
            BigDecimal ageHeightMin = Objects.isNull(heightAgeInfo.getMinValue()) ? BigDecimal.ZERO : heightAgeInfo.getMinValue();
            BigDecimal ageHeightMax = Objects.isNull(heightAgeInfo.getMaxValue()) ? BigDecimal.ZERO : heightAgeInfo.getMaxValue();
            analysisVO.setAgeHeightMin(ageHeightMin);
            analysisVO.setAgeHeightMax(ageHeightMax);
            //判断年龄身高比是否达标
            if (heightScore.compareTo(ageHeightMin) >= 0 && heightScore.compareTo(ageHeightMax) <= 0) {
                analysisVO.setAgeHeightDescription("达标");
            } else {
                analysisVO.setAgeHeightDescription("");
            }
            //年龄体重比信息
            HeightWeightInfo weightAgeInfo = weightInfoMap.getOrDefault(ItemFlagEnum.WEIGHT.getInfo(), new HeightWeightInfo());
            BigDecimal ageWeightMin = Objects.isNull(weightAgeInfo.getMinValue()) ? BigDecimal.ZERO : weightAgeInfo.getMinValue();
            BigDecimal ageWeightMax = Objects.isNull(weightAgeInfo.getMaxValue()) ? BigDecimal.ZERO : weightAgeInfo.getMaxValue();
            analysisVO.setAgeWeightMin(ageWeightMin);
            analysisVO.setAgeWeightMax(ageWeightMax);
            //判断年龄身高比是否达标
            if (weightScore.compareTo(ageWeightMin) >= 0 && heightScore.compareTo(ageWeightMax) <= 0) {
                analysisVO.setAgeWeightDescription("达标");
            } else {
                analysisVO.setAgeWeightDescription("");
            }
        }
    }

    /**
     * 查询BMI项目区级信息
     *
     * @param analysisVO 返回值对应
     * @param itemCode   项目编号
     * @param bmiScore   BIM成绩
     */
    private void getBmiItemInfo(BodyShapeAnalysisVO analysisVO, String itemCode, BigDecimal bmiScore) {
        List<TestItemLevel> testItemsLevelList = testItemsMapper.getTestItemsLevelList(itemCode);
        if (CollectionUtils.isNotEmpty(testItemsLevelList)) {
            for (TestItemLevel testItemLevel : testItemsLevelList) {
                if (Objects.nonNull(testItemLevel.getLevelMinScore()) && Objects.nonNull(testItemLevel.getLevelMaxScore())) {
                    if (bmiScore.compareTo(testItemLevel.getLevelMinScore()) >= 0 && bmiScore.compareTo(testItemLevel.getLevelMaxScore()) <= 0) {
                        analysisVO.setBmiDescription(StringUtils.isBlank(testItemLevel.getLevelName()) ? "" : testItemLevel.getLevelName());
                    }
                }
            }
            analysisVO.setBmiItemLevel(testItemsLevelList);
        }
    }
}
