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

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.enums.WriteDirectionEnum;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.excel.write.metadata.fill.FillWrapper;
import com.github.pagehelper.PageInfo;
import com.xinyilu.common.constant.Constants;
import com.xinyilu.common.constant.HttpStatus;
import com.xinyilu.common.constant.ScoreExportConstants;
import com.xinyilu.common.core.domain.entity.SysRole;
import com.xinyilu.common.core.page.TableDataInfo;
import com.xinyilu.common.enums.ItemCodeEnums;
import com.xinyilu.common.enums.ScoreExportEnum;
import com.xinyilu.common.enums.TestItemCategoryEnum;
import com.xinyilu.common.exception.ServiceException;
import com.xinyilu.common.utils.AgeUtil;
import com.xinyilu.common.utils.BigDecimalUtil;
import com.xinyilu.common.utils.PageServiceUtil;
import com.xinyilu.common.utils.SecurityUtils;
import com.xinyilu.system.domain.dto.ScoreExportDTO;
import com.xinyilu.system.domain.systemarea.SysArea;
import com.xinyilu.system.domain.vo.kinderPhysiqueAnalysis.FirstCategoryScoreVO;
import com.xinyilu.system.domain.vo.kinderPhysiqueAnalysis.KinderCategoryScoreVO;
import com.xinyilu.system.domain.vo.kindergartenSideAnalysis.KindergartenTestItemVO;
import com.xinyilu.system.domain.vo.scoreExport.PhysicalActionScoreVO;
import com.xinyilu.system.domain.vo.scoreExport.ScoreExportVO;
import com.xinyilu.system.mapper.classinfo.ClassInfoMapper;
import com.xinyilu.system.mapper.kindergarteninfo.KindergartenInfoMapper;
import com.xinyilu.system.mapper.systemarea.SysAreaMapper;
import com.xinyilu.system.mapper.testItem.TestItemsMapper;
import com.xinyilu.system.service.scoreExport.ScoreExportKindergartenService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 体侧成绩数据成绩导出
 *
 * @author wanghao
 * @create 2023/8/8 0008
 */
@Service
public class ScoreExportKindergartenServiceImpl implements ScoreExportKindergartenService {


    @Resource
    private TestItemsMapper testItemsMapper;
    @Resource
    private ClassInfoMapper classInfoMapper;
    @Resource
    private KindergartenInfoMapper kindergartenInfoMapper;
    @Resource
    private PageServiceUtil pageServiceUtil;
    @Resource
    private SysAreaMapper sysAreaMapper;

    /**
     * 导出测试分类和测试项目关系列表(班级)
     */
    @Override
    public void scoreExportByClass(HttpServletResponse response, ScoreExportDTO scoreExportDTO) throws IOException {
        //根据用户绑定区域
        List<Long> kindergartenByUser = getKindergartenByUser();
        if (Objects.isNull(kindergartenByUser)) {
            throw new ServiceException("此批次暂无数据");
        }
        scoreExportDTO.setKindergartenIdList(kindergartenByUser);
        //查询测试项目信息
        List<Long> classInfo = testItemsMapper.getClassByScoreExport(scoreExportDTO);
        if (CollectionUtils.isEmpty(classInfo)) {
            throw new ServiceException("该幼儿园此批次暂无数据");
        }
        scoreExportDTO.setItemCode(ItemCodeEnums.BMI_CODE.getInfo());
        //查询测试项目信息
        List<PhysicalActionScoreVO> physicalActionScoreVO = testItemsMapper.scoreExportByClass(scoreExportDTO);
        //查询测试项目分类信息
        List<KinderCategoryScoreVO> itemCategoryScore = kindergartenInfoMapper.getItemCategoryScoreGroupByClassId(scoreExportDTO);
        //查询每个分类的成绩信息
        List<KinderCategoryScoreVO> categoryScoreInfoList = kindergartenInfoMapper.getKinderCategoryScoreInfoByClass(scoreExportDTO);
        //一级分类父级id
        List<KinderCategoryScoreVO> getTestItemCategoryParentId = kindergartenInfoMapper.getTestItemCategoryParentId(ItemCodeEnums.BMI_CODE.getInfo());
        //计算每个一级分类的平均得分
        for (KinderCategoryScoreVO kinderCategoryScoreVO : itemCategoryScore) {
            kinderCategoryScoreVO.setParentId(getTestItemCategoryParentId.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getItemCode()) && item.getItemCode().equals(kinderCategoryScoreVO.getItemCode())).findFirst().orElseGet(KinderCategoryScoreVO::new).getParentId());
            kinderCategoryScoreVO.setId(getTestItemCategoryParentId.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getItemCode()) && item.getItemCode().equals(kinderCategoryScoreVO.getItemCode())).findFirst().orElseGet(KinderCategoryScoreVO::new).getId());
            kinderCategoryScoreVO.setCategoryName(getTestItemCategoryParentId.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getItemCode()) && item.getItemCode().equals(kinderCategoryScoreVO.getItemCode())).findFirst().orElseGet(KinderCategoryScoreVO::new).getCategoryName());
        }
        List<ScoreExportVO> scoreExportList = new ArrayList<>();
        //根据班级id的唯一性,进行分组
        Map<Long, List<PhysicalActionScoreVO>> itemScoreMap = physicalActionScoreVO.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getClassId())).collect(Collectors.groupingBy(PhysicalActionScoreVO::getClassId));
        Map<Long, List<KinderCategoryScoreVO>> itemCategoryScoreMap = itemCategoryScore.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getClassId())).collect(Collectors.groupingBy(KinderCategoryScoreVO::getClassId));
        Map<Long, List<KinderCategoryScoreVO>> categoryScoreInfoMap = categoryScoreInfoList.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getClassId())).collect(Collectors.groupingBy(KinderCategoryScoreVO::getClassId));
        for (Long classIds : classInfo) {
            List<PhysicalActionScoreVO> physicalActionScoreVOList = itemScoreMap.get(classIds);
            scoreExportDTO.setClassId(classIds);
            Long studentCount = kindergartenInfoMapper.getItemCategoryStudentCount(scoreExportDTO);
            List<KinderCategoryScoreVO> kinderCategoryScoreList = itemCategoryScoreMap.get(classIds);
            List<KinderCategoryScoreVO> categoryScoreByClass = categoryScoreInfoMap.get(classIds);
            ScoreExportVO scoreExportVO = classInfoMapper.getInfoByClassId(classIds, null, scoreExportDTO.getSex(),scoreExportDTO.getBatchCode());
            scoreExportVO.setAge(getAvgAge(classInfoMapper.getBirthDateClassId(classIds, null, scoreExportDTO.getSex())));
            //判断动作发展状况,塞入数据
            this.setItemScore(scoreExportVO, physicalActionScoreVOList);
            //塞入测试总成绩/国民体质测试平均分/运动测试平均分
            this.getTestSumScore(scoreExportVO, kinderCategoryScoreList, studentCount);
            //塞入测试项目分类数据信息
            this.getCategoryLevelInfo(scoreExportVO, categoryScoreByClass, studentCount);
            scoreExportList.add(scoreExportVO);
        }
        //设置编号
        int serial = 1;
        for (ScoreExportVO scoreExportVO : scoreExportList) {
            scoreExportVO.setSerial(serial++);
        }
        //组装数据
        Map<String, Object> map = new HashMap<>(2);
        map.put("bachCode", scoreExportDTO.getBatchCode());
        map.put("sex", getSexName(scoreExportDTO.getSex()));
        // 模版文件
        OutputStream outputStream = response.getOutputStream();
        ClassPathResource classPathResource = new ClassPathResource("template/幼儿体质健康评价班级成绩表.xlsx");
        InputStream inputStream = classPathResource.getInputStream();
        ExcelWriter excelWriter = EasyExcel.write(outputStream).withTemplate(inputStream).excelType(ExcelTypeEnum.XLSX).autoCloseStream(Boolean.FALSE).build();
        WriteSheet writeSheet = EasyExcel.writerSheet().build();
        FillConfig fillConfig = FillConfig.builder().direction(WriteDirectionEnum.VERTICAL).forceNewRow(Boolean.TRUE).build();
        excelWriter.fill(map, writeSheet);
        excelWriter.fill(new FillWrapper("data", scoreExportList), fillConfig, writeSheet);
        excelWriter.finish();
    }

    /**
     * 导出测试分类和测试项目关系列表(幼儿园)
     */
    @Override
    public void scoreExportByKindergarten(HttpServletResponse response, ScoreExportDTO scoreExportDTO) throws IOException {
        //根据用户绑定区域
        List<Long> kindergartenByUser = getKindergartenByUser();
        if (Objects.isNull(kindergartenByUser)) {
            throw new ServiceException("此批次暂无数据");
        }
        scoreExportDTO.setKindergartenIdList(kindergartenByUser);
        List<Long> kindergartenInfo = testItemsMapper.getKindergartenByScoreExport(scoreExportDTO);
        if (CollectionUtils.isEmpty(kindergartenInfo)) {
            throw new ServiceException("此批次暂无数据");
        }
        scoreExportDTO.setItemCode(ItemCodeEnums.BMI_CODE.getInfo());
        //查询测试项目信息
        List<PhysicalActionScoreVO> physicalActionScoreVO = testItemsMapper.scoreExportByKindergarten(scoreExportDTO);
        //查询测试项目分类信息
        List<KinderCategoryScoreVO> itemCategoryScore = kindergartenInfoMapper.getItemCategoryScoreGroupByKindergartenId(scoreExportDTO);
        //查询每个分类的成绩信息
        List<KinderCategoryScoreVO> categoryScoreInfoList = kindergartenInfoMapper.getKinderCategoryScoreInfoByKindergarten(scoreExportDTO);
        //一级分类父级id
        List<KinderCategoryScoreVO> getTestItemCategoryParentId = kindergartenInfoMapper.getTestItemCategoryParentId(ItemCodeEnums.BMI_CODE.getInfo());
        //计算每个一级分类的平均得分
        for (KinderCategoryScoreVO kinderCategoryScoreVO : itemCategoryScore) {
            kinderCategoryScoreVO.setParentId(getTestItemCategoryParentId.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getItemCode()) && item.getItemCode().equals(kinderCategoryScoreVO.getItemCode())).findFirst().orElseGet(KinderCategoryScoreVO::new).getParentId());
            kinderCategoryScoreVO.setId(getTestItemCategoryParentId.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getItemCode()) && item.getItemCode().equals(kinderCategoryScoreVO.getItemCode())).findFirst().orElseGet(KinderCategoryScoreVO::new).getId());
            kinderCategoryScoreVO.setCategoryName(getTestItemCategoryParentId.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getItemCode()) && item.getItemCode().equals(kinderCategoryScoreVO.getItemCode())).findFirst().orElseGet(KinderCategoryScoreVO::new).getCategoryName());
        }
        List<ScoreExportVO> scoreExportList = new ArrayList<>();
        //根据幼儿园id的唯一性,进行分组
        Map<Long, List<PhysicalActionScoreVO>> itemScoreMap = physicalActionScoreVO.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getKindergartenId())).collect(Collectors.groupingBy(PhysicalActionScoreVO::getKindergartenId));
        Map<Long, List<KinderCategoryScoreVO>> itemCategoryScoreMap = itemCategoryScore.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getKindergartenId())).collect(Collectors.groupingBy(KinderCategoryScoreVO::getKindergartenId));
        Map<Long, List<KinderCategoryScoreVO>> categoryScoreInfoMap = categoryScoreInfoList.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getKindergartenId())).collect(Collectors.groupingBy(KinderCategoryScoreVO::getKindergartenId));
        for (Long kindergartenId : kindergartenInfo) {
            List<PhysicalActionScoreVO> physicalActionScoreVOList = itemScoreMap.get(kindergartenId);
            scoreExportDTO.setKindergartenId(kindergartenId);
            Long studentCount = kindergartenInfoMapper.getItemCategoryStudentCount(scoreExportDTO);
            List<KinderCategoryScoreVO> kinderCategoryScoreList = itemCategoryScoreMap.get(kindergartenId);
            List<KinderCategoryScoreVO> categoryScoreByKindergarten = categoryScoreInfoMap.get(kindergartenId);
            ScoreExportVO scoreExportVO = classInfoMapper.getInfoByClassId(null, kindergartenId, scoreExportDTO.getSex(),scoreExportDTO.getBatchCode());
            scoreExportVO.setAge(getAvgAge(classInfoMapper.getBirthDateClassId(null, kindergartenId, scoreExportDTO.getSex())));
            //判断动作发展状况,塞入数据
            this.setItemScore(scoreExportVO, physicalActionScoreVOList);
            //塞入测试总成绩/国民体质测试平均分/运动测试平均分
            this.getTestSumScore(scoreExportVO, kinderCategoryScoreList, studentCount);
            //塞入测试项目分类数据信息
            this.getCategoryLevelInfo(scoreExportVO, categoryScoreByKindergarten, studentCount);
            //达标率计算
            List<Long> nationalPhysiqueList = Arrays.asList(ScoreExportConstants.NATIONAL_PHYSIQUE_ONE, ScoreExportConstants.NATIONAL_PHYSIQUE_TWO, ScoreExportConstants.NATIONAL_PHYSIQUE_THREE, ScoreExportConstants.NATIONAL_PHYSIQUE_FOUR, ScoreExportConstants.NATIONAL_PHYSIQUE_FIVE, ScoreExportConstants.NATIONAL_PHYSIQUE_SIX, ScoreExportConstants.NATIONAL_PHYSIQUE_NINETEEN, ScoreExportConstants.NATIONAL_PHYSIQUE_TWENTY);
            List<KindergartenTestItemVO> testItemList = kindergartenInfoMapper.getTestItemList(kindergartenId, scoreExportDTO.getBatchCode(), nationalPhysiqueList, ItemCodeEnums.BMI_CODE.getInfo());//达标率计算
            if (CollectionUtils.isNotEmpty(testItemList)) {
                getTestItemList(testItemList, studentCount.intValue(), scoreExportVO);
            }
            scoreExportList.add(scoreExportVO);
        }
        //设置编号
        int serial = 1;
        for (ScoreExportVO scoreExportVO : scoreExportList) {
            scoreExportVO.setSerial(serial++);
        }
        //组装数据
        Map<String, Object> map = new HashMap<>();
        map.put("bachCode", scoreExportDTO.getBatchCode());
        map.put("sex", getSexName(scoreExportDTO.getSex()));
        //模版文件
        OutputStream outputStream = response.getOutputStream();
        ClassPathResource classPathResource = new ClassPathResource("template/幼儿体质健康评价幼儿园成绩表.xlsx");
        InputStream inputStream = classPathResource.getInputStream();
        ExcelWriter excelWriter = EasyExcel.write(outputStream).withTemplate(inputStream).excelType(ExcelTypeEnum.XLSX).autoCloseStream(Boolean.FALSE).build();
        WriteSheet writeSheet = EasyExcel.writerSheet().build();
        FillConfig fillConfig = FillConfig.builder().direction(WriteDirectionEnum.VERTICAL).forceNewRow(Boolean.TRUE).build();
        excelWriter.fill(map, writeSheet);
        excelWriter.fill(new FillWrapper("data", scoreExportList), fillConfig, writeSheet);
        excelWriter.finish();
    }

    /**
     * 测试分类和测试项目关系列表(班级)
     *
     * @param scoreExportDTO，
     */
    @Override
    public TableDataInfo scoreByClassList(ScoreExportDTO scoreExportDTO) {
        //根据用户绑定区域
        List<Long> kindergartenByUser = getKindergartenByUser();
        if (Objects.isNull(kindergartenByUser)) {
            return pageServiceUtil.getDataTable(new ArrayList<>());
        }
        scoreExportDTO.setKindergartenIdList(kindergartenByUser);
        //查询测试项目信息
        pageServiceUtil.startPage();
        List<Long> classInfo = testItemsMapper.getClassByScoreExport(scoreExportDTO);
        if (CollectionUtils.isEmpty(classInfo)) {
            return pageServiceUtil.getDataTable(classInfo);
        }
        scoreExportDTO.setItemCode(ItemCodeEnums.BMI_CODE.getInfo());
        List<PhysicalActionScoreVO> physicalActionScoreVO = testItemsMapper.scoreExportByClass(scoreExportDTO);
        //查询测试项目分类信息
        List<KinderCategoryScoreVO> itemCategoryScore = kindergartenInfoMapper.getItemCategoryScoreGroupByClassId(scoreExportDTO);
        //查询每个分类的成绩信息
        List<KinderCategoryScoreVO> categoryScoreInfoList = kindergartenInfoMapper.getKinderCategoryScoreInfoByClass(scoreExportDTO);
        //一级分类父级id
        List<KinderCategoryScoreVO> getTestItemCategoryParentId = kindergartenInfoMapper.getTestItemCategoryParentId(ItemCodeEnums.BMI_CODE.getInfo());
        //计算每个一级分类的平均得分
        for (KinderCategoryScoreVO kinderCategoryScoreVO : itemCategoryScore) {
            kinderCategoryScoreVO.setParentId(getTestItemCategoryParentId.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getItemCode()) && item.getItemCode().equals(kinderCategoryScoreVO.getItemCode())).findFirst().orElseGet(KinderCategoryScoreVO::new).getParentId());
            kinderCategoryScoreVO.setId(getTestItemCategoryParentId.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getItemCode()) && item.getItemCode().equals(kinderCategoryScoreVO.getItemCode())).findFirst().orElseGet(KinderCategoryScoreVO::new).getId());
            kinderCategoryScoreVO.setCategoryName(getTestItemCategoryParentId.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getItemCode()) && item.getItemCode().equals(kinderCategoryScoreVO.getItemCode())).findFirst().orElseGet(KinderCategoryScoreVO::new).getCategoryName());
        }
        List<ScoreExportVO> scoreExportList = new ArrayList<>();
        //根据班级id的唯一性,进行分组
        Map<Long, List<PhysicalActionScoreVO>> itemScoreMap = physicalActionScoreVO.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getClassId())).collect(Collectors.groupingBy(PhysicalActionScoreVO::getClassId));
        Map<Long, List<KinderCategoryScoreVO>> itemCategoryScoreMap = itemCategoryScore.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getClassId())).collect(Collectors.groupingBy(KinderCategoryScoreVO::getClassId));
        Map<Long, List<KinderCategoryScoreVO>> categoryScoreInfoMap = categoryScoreInfoList.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getClassId())).collect(Collectors.groupingBy(KinderCategoryScoreVO::getClassId));
        for (Long classIds : classInfo) {
            List<PhysicalActionScoreVO> physicalActionScoreVOList = itemScoreMap.get(classIds);
            scoreExportDTO.setClassId(classIds);
            Long studentCount = kindergartenInfoMapper.getItemCategoryStudentCount(scoreExportDTO);
            List<KinderCategoryScoreVO> kinderCategoryScoreList = itemCategoryScoreMap.get(classIds);
            List<KinderCategoryScoreVO> categoryScoreByClass = categoryScoreInfoMap.get(classIds);
            ScoreExportVO scoreExportVO = classInfoMapper.getInfoByClassId(classIds, null, scoreExportDTO.getSex(),scoreExportDTO.getBatchCode());
            scoreExportVO.setAge(getAvgAge(classInfoMapper.getBirthDateClassId(classIds, null, scoreExportDTO.getSex())));
            //判断动作发展状况,塞入数据
            this.setItemScore(scoreExportVO, physicalActionScoreVOList);
            //塞入测试总成绩/国民体质测试平均分/运动测试平均分
            this.getTestSumScore(scoreExportVO, kinderCategoryScoreList, studentCount);
            //塞入测试项目分类数据信息
            this.getCategoryLevelInfo(scoreExportVO, categoryScoreByClass, studentCount);
            scoreExportList.add(scoreExportVO);
        }
        //设置编号
        int serial = 1;
        for (ScoreExportVO scoreExportVO : scoreExportList) {
            scoreExportVO.setSerial(serial++);
        }
        TableDataInfo rspData = new TableDataInfo();
        rspData.setCode(HttpStatus.SUCCESS);
        rspData.setMsg("查询成功");
        rspData.setRows(scoreExportList);
        rspData.setTotal(new PageInfo(classInfo).getTotal());
        return rspData;
    }

    /**
     * 测试分类和测试项目关系列表(幼儿园)
     *
     * @param scoreExportDTO，
     */
    @Override
    public TableDataInfo scoreByKindergartenList(ScoreExportDTO scoreExportDTO) {
        //根据用户绑定区域
        List<Long> kindergartenByUser = getKindergartenByUser();
        if (Objects.isNull(kindergartenByUser)) {
            return pageServiceUtil.getDataTable(new ArrayList<>());
        }
        scoreExportDTO.setKindergartenIdList(kindergartenByUser);
        //查询测试项目信息
        pageServiceUtil.startPage();
        List<Long> kindergartenInfo = testItemsMapper.getKindergartenByScoreExport(scoreExportDTO);
        if (CollectionUtils.isEmpty(kindergartenInfo)) {
            return pageServiceUtil.getDataTable(kindergartenInfo);
        }
        scoreExportDTO.setItemCode(ItemCodeEnums.BMI_CODE.getInfo());
        //查询测试项目信息
        List<PhysicalActionScoreVO> physicalActionScoreVO = testItemsMapper.scoreExportByKindergarten(scoreExportDTO);
        //查询测试项目分类信息
        List<KinderCategoryScoreVO> itemCategoryScore = kindergartenInfoMapper.getItemCategoryScoreGroupByKindergartenId(scoreExportDTO);
        //查询每个分类的成绩信息
        List<KinderCategoryScoreVO> categoryScoreInfoList = kindergartenInfoMapper.getKinderCategoryScoreInfoByKindergarten(scoreExportDTO);
        //一级分类父级id
        List<KinderCategoryScoreVO> getTestItemCategoryParentId = kindergartenInfoMapper.getTestItemCategoryParentId(ItemCodeEnums.BMI_CODE.getInfo());
        //计算每个一级分类的平均得分
        for (KinderCategoryScoreVO kinderCategoryScoreVO : itemCategoryScore) {
            kinderCategoryScoreVO.setParentId(getTestItemCategoryParentId.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getItemCode()) && item.getItemCode().equals(kinderCategoryScoreVO.getItemCode())).findFirst().orElseGet(KinderCategoryScoreVO::new).getParentId());
            kinderCategoryScoreVO.setId(getTestItemCategoryParentId.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getItemCode()) && item.getItemCode().equals(kinderCategoryScoreVO.getItemCode())).findFirst().orElseGet(KinderCategoryScoreVO::new).getId());
            kinderCategoryScoreVO.setCategoryName(getTestItemCategoryParentId.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getItemCode()) && item.getItemCode().equals(kinderCategoryScoreVO.getItemCode())).findFirst().orElseGet(KinderCategoryScoreVO::new).getCategoryName());
        }
        List<ScoreExportVO> scoreExportList = new ArrayList<>();
        //根据幼儿园id的唯一性,进行分组
        Map<Long, List<PhysicalActionScoreVO>> itemScoreMap = physicalActionScoreVO.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getKindergartenId())).collect(Collectors.groupingBy(PhysicalActionScoreVO::getKindergartenId));
        Map<Long, List<KinderCategoryScoreVO>> itemCategoryScoreMap = itemCategoryScore.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getKindergartenId())).collect(Collectors.groupingBy(KinderCategoryScoreVO::getKindergartenId));
        Map<Long, List<KinderCategoryScoreVO>> categoryScoreInfoMap = categoryScoreInfoList.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getKindergartenId())).collect(Collectors.groupingBy(KinderCategoryScoreVO::getKindergartenId));
        for (Long kindergartenId : kindergartenInfo) {
            List<PhysicalActionScoreVO> physicalActionScoreVOList = itemScoreMap.get(kindergartenId);
            scoreExportDTO.setKindergartenId(kindergartenId);
            Long studentCount = kindergartenInfoMapper.getItemCategoryStudentCount(scoreExportDTO);
            List<KinderCategoryScoreVO> kinderCategoryScoreList = itemCategoryScoreMap.get(kindergartenId);
            List<KinderCategoryScoreVO> categoryScoreByKindergarten = categoryScoreInfoMap.get(kindergartenId);
            ScoreExportVO scoreExportVO = classInfoMapper.getInfoByClassId(null, kindergartenId, scoreExportDTO.getSex(),scoreExportDTO.getBatchCode());
            scoreExportVO.setAge(getAvgAge(classInfoMapper.getBirthDateClassId(null, kindergartenId, scoreExportDTO.getSex())));
            //判断动作发展状况,塞入数据
            this.setItemScore(scoreExportVO, physicalActionScoreVOList);
            //塞入测试总成绩/国民体质测试平均分/运动测试平均分
            this.getTestSumScore(scoreExportVO, kinderCategoryScoreList, studentCount);
            //塞入测试项目分类数据信息
            this.getCategoryLevelInfo(scoreExportVO, categoryScoreByKindergarten, studentCount);
            //达标率计算
            List<Long> nationalPhysiqueList = Arrays.asList(ScoreExportConstants.NATIONAL_PHYSIQUE_ONE, ScoreExportConstants.NATIONAL_PHYSIQUE_TWO, ScoreExportConstants.NATIONAL_PHYSIQUE_THREE, ScoreExportConstants.NATIONAL_PHYSIQUE_FOUR, ScoreExportConstants.NATIONAL_PHYSIQUE_FIVE, ScoreExportConstants.NATIONAL_PHYSIQUE_SIX, ScoreExportConstants.NATIONAL_PHYSIQUE_NINETEEN, ScoreExportConstants.NATIONAL_PHYSIQUE_TWENTY);
            List<KindergartenTestItemVO> testItemList = kindergartenInfoMapper.getTestItemList(kindergartenId, scoreExportDTO.getBatchCode(), nationalPhysiqueList, ItemCodeEnums.BMI_CODE.getInfo());//达标率计算
            if (CollectionUtils.isNotEmpty(testItemList)) {
                getTestItemList(testItemList, studentCount.intValue(), scoreExportVO);
            }
            scoreExportList.add(scoreExportVO);
        }
        //设置编号
        int serial = 1;
        for (ScoreExportVO scoreExportVO : scoreExportList) {
            scoreExportVO.setSerial(serial++);
        }
        TableDataInfo rspData = new TableDataInfo();
        rspData.setCode(HttpStatus.SUCCESS);
        rspData.setMsg("查询成功");
        rspData.setRows(scoreExportList);
        rspData.setTotal(new PageInfo(kindergartenInfo).getTotal());
        return rspData;
    }

    /**
     * 获取年龄的平均值
     */
    public BigDecimal getAvgAge(List<Date> dates) {
        BigDecimal avgAge = BigDecimal.valueOf(0);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        for (Date date : dates) {
            avgAge = avgAge.add(BigDecimal.valueOf(AgeUtil.getStudentAgeMonth(simpleDateFormat.format(date))));
        }
        if (avgAge.equals(BigDecimal.ZERO)) {
            return BigDecimal.valueOf(0);
        }
        return avgAge.divide(BigDecimal.valueOf(dates.size()), 1, RoundingMode.HALF_UP);
    }

    /**
     * 塞入体测成绩数据
     *
     * @param scoreExportVO 体测成绩数据
     */
    public void setItemScore(ScoreExportVO scoreExportVO, List<PhysicalActionScoreVO> physicalActionScoreList) {
        for (PhysicalActionScoreVO data : physicalActionScoreList) {
            //身高
            if (ScoreExportEnum.HEIGHT_CODE.getInfo().equals(data.getItemCode())) {
                scoreExportVO.setHeightScore(data.getAvgScore());
                scoreExportVO.setHeightFraction(data.getAvgFraction());
            }
            //体重
            if (ScoreExportEnum.WEIGHT_CODE.getInfo().equals(data.getItemCode())) {
                scoreExportVO.setWeightScore(data.getAvgScore());
                scoreExportVO.setWeightFraction(data.getAvgFraction());
            }
            //BMI
            if (ScoreExportEnum.BMI_CODE.getInfo().equals(data.getItemCode())) {
                scoreExportVO.setBmiScore(data.getAvgScore());
                scoreExportVO.setBmiFraction(data.getAvgFraction());
            }
            //立定跳远
            if (ScoreExportEnum.LONG_JUMP_CODE.getInfo().equals(data.getItemCode())) {
                scoreExportVO.setLongJumpScore(data.getAvgScore());
                scoreExportVO.setLongJumpFraction(data.getAvgFraction());
            }
            //双脚连续跳
            if (ScoreExportEnum.CONTINUOUS_JUMP_CODE.getInfo().equals(data.getItemCode())) {
                scoreExportVO.setContinuousJumpScore(data.getAvgScore());
                scoreExportVO.setContinuousJumpFraction(data.getAvgFraction());
            }
            //网球掷远
            if (ScoreExportEnum.TENNIS_CODE.getInfo().equals(data.getItemCode())) {
                scoreExportVO.setTennisScore(data.getAvgScore());
                scoreExportVO.setTennisFraction(data.getAvgFraction());
            }
            //走平衡木
            if (ScoreExportEnum.BALANCE_BEAM_CODE.getInfo().equals(data.getItemCode())) {
                scoreExportVO.setBalanceBeamScore(data.getAvgScore());
                scoreExportVO.setBalanceBeamFraction(data.getAvgFraction());
            }
            //坐位体前屈
            if (ScoreExportEnum.SIT_AND_REACH_CODE.getInfo().equals(data.getItemCode())) {
                scoreExportVO.setSitAndReachScore(data.getAvgScore());
                scoreExportVO.setSitAndReachFraction(data.getAvgFraction());
            }
            //10米折返跑项目
            if (ScoreExportEnum.SHUTTLE_RUN_CODE.getInfo().equals(data.getItemCode())) {
                scoreExportVO.setShuttleRunScore(data.getAvgScore());
                scoreExportVO.setShuttleRunFraction(data.getAvgFraction());
            }
            //10米折返跑项目
            if (ScoreExportEnum.SHUTTLE_RUN_CODE.getInfo().equals(data.getItemCode())) {
                scoreExportVO.setShuttleRunScore(data.getAvgScore());
                scoreExportVO.setShuttleRunFraction(data.getAvgFraction());
            }
            //T跑
            if (ScoreExportEnum.T_RUN_CODE.getInfo().equals(data.getItemCode())) {
                scoreExportVO.setTrunScore(data.getAvgScore());
            }
            //T立定跳远
            if (ScoreExportEnum.T_LONG_JUMP_CODE.getInfo().equals(data.getItemCode())) {
                scoreExportVO.setTlongJumpScore(data.getAvgScore());
            }
            // T单脚跳
            if (ScoreExportEnum.T_HOP_CODE.getInfo().equals(data.getItemCode())) {
                scoreExportVO.setThopScore(data.getAvgScore());
            }
            // T前跨跳
            if (ScoreExportEnum.T_FORWARD_JUMP_CODE.getInfo().equals(data.getItemCode())) {
                scoreExportVO.setTforwardJumpScore(data.getAvgScore());
            }
            // T前滑步
            if (ScoreExportEnum.T_FORWARD_SLIDING_STEP_CODE.getInfo().equals(data.getItemCode())) {
                scoreExportVO.setTforwardSlidingStepScore(data.getAvgScore());
            }
            // T侧滑步
            if (ScoreExportEnum.T_SIDE_STEP_CODE.getInfo().equals(data.getItemCode())) {
                scoreExportVO.setTsideStepScore(data.getAvgScore());
            }
            // T原地拍球
            if (ScoreExportEnum.T_RACKET_BALL_CODE.getInfo().equals(data.getItemCode())) {
                scoreExportVO.setTracketBallScore(data.getAvgScore());
            }
            // T踢球
            if (ScoreExportEnum.T_PLAY_FOOTBALL_CODE.getInfo().equals(data.getItemCode())) {
                scoreExportVO.setTplayFootballScore(data.getAvgScore());
            }
            // T双手接球
            if (ScoreExportEnum.T_TWO_HANDED_CATCH_CODE.getInfo().equals(data.getItemCode())) {
                scoreExportVO.setTtwoHandedCatchScore(data.getAvgScore());
            }
            // T击固定球
            if (ScoreExportEnum.T_FIXED_BALL_CODE.getInfo().equals(data.getItemCode())) {
                scoreExportVO.setTfixedBallScore(data.getAvgScore());
            }
            // T上手投球
            if (ScoreExportEnum.T_OVERHAND_PITCHING_CODE.getInfo().equals(data.getItemCode())) {
                scoreExportVO.setToverhandPitchingScore(data.getAvgScore());
            }
            // T地滚球
            if (ScoreExportEnum.T_GROUNDER_CODE.getInfo().equals(data.getItemCode())) {
                scoreExportVO.setTgrounderScore(data.getAvgScore());
            }
        }
    }

    /**
     * 获取测试总成绩/国民体质测试平均分/运动测试平均分
     *
     * @param list         各项目分类分数
     * @param studentCount 学生数量
     */
    public void getTestSumScore(ScoreExportVO scoreExportVO, List<KinderCategoryScoreVO> list, Long studentCount) {
        Map<Long, List<KinderCategoryScoreVO>> firstCategoryMap = list.stream().filter(item -> Objects.nonNull(item.getParentId())).collect(Collectors.groupingBy(KinderCategoryScoreVO::getParentId));
        List<FirstCategoryScoreVO> firstCategoryScoreList = Lists.newArrayList();
        for (Map.Entry<Long, List<KinderCategoryScoreVO>> categoryEntry : firstCategoryMap.entrySet()) {
            List<KinderCategoryScoreVO> categoryScoreList = categoryEntry.getValue();
            if (CollectionUtils.isEmpty(categoryScoreList)) {
                continue;
            }
            //每个分类的总成绩相加
            BigDecimal totalScore = categoryScoreList.stream().filter(Objects::nonNull).map(KinderCategoryScoreVO::getItemFraction).reduce(BigDecimal.ZERO, BigDecimal::add);
            FirstCategoryScoreVO categoryScoreVO = new FirstCategoryScoreVO();
            categoryScoreVO.setCategoryName(categoryScoreList.get(0).getCategoryName());
            if (studentCount != 0) {
                categoryScoreVO.setAvgCategoryFraction(BigDecimalUtil.getAvgScore(BigDecimal.valueOf(studentCount), totalScore));
            } else {
                categoryScoreVO.setAvgCategoryFraction(BigDecimal.ZERO);
            }
            firstCategoryScoreList.add(categoryScoreVO);
        }
        //塞入国民体质测试平均分和T运动测试平均分
        if (CollectionUtils.isNotEmpty(firstCategoryScoreList)) {
            for (FirstCategoryScoreVO firstCategoryScoreVO : firstCategoryScoreList) {
                if (TestItemCategoryEnum.NATIONAL_PHYSIQUE_CODE.getInfo().equals(firstCategoryScoreVO.getCategoryName())) {
                    scoreExportVO.setNationalPhysiqueScore(firstCategoryScoreVO.getAvgCategoryFraction());
                }
                if (TestItemCategoryEnum.T_EXERCISE_TESTING_CODE.getInfo().equals(firstCategoryScoreVO.getCategoryName())) {
                    scoreExportVO.setTexerciseTestingScore(firstCategoryScoreVO.getAvgCategoryFraction());
                }
            }
        }
        //该学校、该批次、该性别的总人数
        BigDecimal bigDecimal = list.stream().map(KinderCategoryScoreVO::getItemFraction).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, RoundingMode.HALF_UP);
        //查出来总成绩
        BigDecimal divide = bigDecimal.divide(new BigDecimal(studentCount), 2, RoundingMode.HALF_UP);
        scoreExportVO.setTestSumScore(divide);
    }

    /**
     * 每个分类的得分区间信息
     *
     * @param categoryScoreInfoList 每个分类的成绩信息
     */
    private void getCategoryLevelInfo(ScoreExportVO scoreExportVO,
                                      List<KinderCategoryScoreVO> categoryScoreInfoList,
                                      Long studentNum) {
        //计算每个分类的平均得分以及每个分类的平均得分描述信息
        for (KinderCategoryScoreVO score : categoryScoreInfoList) {
            this.setCategoryName(score, studentNum);
        }
        //将一级分类信息去除
        List<KinderCategoryScoreVO> distinctScoreList = categoryScoreInfoList.stream().filter(item -> Objects.nonNull(item.getId())).distinct().collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(distinctScoreList)) {
            for (KinderCategoryScoreVO kinderCategoryScoreVO : distinctScoreList) {
                if (TestItemCategoryEnum.BODY_SHAPE_CODE.getInfo().equals(kinderCategoryScoreVO.getCategoryName())) {
                    scoreExportVO.setBodyShapeScore(kinderCategoryScoreVO.getAvgItemFraction());
                }
                if (TestItemCategoryEnum.EXPLOSIVE_QUALITY_CODE.getInfo().equals(kinderCategoryScoreVO.getCategoryName())) {
                    scoreExportVO.setExplosiveQualityScore(kinderCategoryScoreVO.getAvgItemFraction());
                }
                if (TestItemCategoryEnum.COORDINATION_QUALITY_CODE.getInfo().equals(kinderCategoryScoreVO.getCategoryName())) {
                    scoreExportVO.setCoordinationQualityScore(kinderCategoryScoreVO.getAvgItemFraction());
                }
                if (TestItemCategoryEnum.LOWER_LIMB_FITNESS_CODE.getInfo().equals(kinderCategoryScoreVO.getCategoryName())) {
                    scoreExportVO.setLowerLimbFitnessScore(kinderCategoryScoreVO.getAvgItemFraction());
                }
                if (TestItemCategoryEnum.UPPER_LIMB_FITNESS_CODE.getInfo().equals(kinderCategoryScoreVO.getCategoryName())) {
                    scoreExportVO.setUpperLimbFitnessScore(kinderCategoryScoreVO.getAvgItemFraction());
                }
                if (TestItemCategoryEnum.CORE_CODE.getInfo().equals(kinderCategoryScoreVO.getCategoryName())) {
                    scoreExportVO.setCoreScore(kinderCategoryScoreVO.getAvgItemFraction());
                }
                if (TestItemCategoryEnum.BALANCED_QUALITY_CODE.getInfo().equals(kinderCategoryScoreVO.getCategoryName())) {
                    scoreExportVO.setBalancedQualityScore(kinderCategoryScoreVO.getAvgItemFraction());
                }
                if (TestItemCategoryEnum.FLEXIBILITY_CODE.getInfo().equals(kinderCategoryScoreVO.getCategoryName())) {
                    scoreExportVO.setFlexibilityScore(kinderCategoryScoreVO.getAvgItemFraction());
                }
                if (TestItemCategoryEnum.AGILITY_CODE.getInfo().equals(kinderCategoryScoreVO.getCategoryName())) {
                    scoreExportVO.setAgilityScore(kinderCategoryScoreVO.getAvgItemFraction());
                }
                if (TestItemCategoryEnum.DISPLACEMENT_MOTION_CODE.getInfo().equals(kinderCategoryScoreVO.getCategoryName())) {
                    scoreExportVO.setControlMotionScore(kinderCategoryScoreVO.getAvgItemFraction());
                }
                if (TestItemCategoryEnum.CONTROL_MOTION_CODE.getInfo().equals(kinderCategoryScoreVO.getCategoryName())) {
                    scoreExportVO.setDisplacementMotionScore(kinderCategoryScoreVO.getAvgItemFraction());
                }
            }
        }
    }

    /**
     * 设置平均得分区间描述信息
     *
     * @param score 得分信息
     */
    private void setCategoryName(KinderCategoryScoreVO score, Long studentNum) {
        if (Objects.nonNull(score.getItemFraction())) {
            score.setAvgItemFraction(score.getItemFraction().divide(new BigDecimal(studentNum), 2, RoundingMode.HALF_UP));
        }
    }

    /**
     * 获取性别中文名称
     *
     * @param sex 性别英文
     */
    private String getSexName(String sex) {
        if (StringUtils.isBlank(sex)) {
            return ScoreExportConstants.SUM;
        } else if (sex.equals(Constants.FEMALE)) {
            return ScoreExportConstants.FEMALE;
        } else {
            return ScoreExportConstants.MALE;
        }
    }

    /**
     * 得到测试项目列表
     *
     * @param testItemList 测试项目列表
     * @param totalCount   总人数
     */
    private void getTestItemList(List<KindergartenTestItemVO> testItemList, int totalCount, ScoreExportVO scoreExportVO) {
        Map<Long, List<KindergartenTestItemVO>> studentIdMp = testItemList.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getStudentId())).collect(Collectors.groupingBy(KindergartenTestItemVO::getStudentId));
        studentIdMp.forEach((studentId, kindergartenTestItem) -> {
            KindergartenTestItemVO kindergartenTestItemVO = kindergartenTestItem.get(0);
            //每个素质的总分数
            BigDecimal testItemSumScore = kindergartenTestItem.stream().filter(item -> Objects.nonNull(item.getAvgScore()))
                    .map(KindergartenTestItemVO::getAvgScore)
                    .reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, BigDecimal.ROUND_HALF_UP);
            kindergartenTestItemVO.setSumScore(testItemSumScore);
        });
        //小于二十分的人  20<
        long twentyCount = testItemList.stream().filter(score -> Objects.nonNull(score.getSumScore()))
                .filter(score -> score.getSumScore().compareTo(ScoreExportConstants.TWENTY_SCORE) < 0).count();
        //达标率
        BigDecimal itemStandardScore = BigDecimal.valueOf(totalCount - twentyCount).divide(BigDecimal.valueOf(totalCount), 4, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100)).setScale(2, RoundingMode.HALF_UP);
        scoreExportVO.setNationalPhysiqueRate(itemStandardScore + "%");
    }

    private List<Long> getKindergartenByUser() {
        //判断当前用户角色，根据不同的角色显示不同的家长信息
        List<String> roleKeys = SecurityUtils.getLoginUser().getUser().getRoles()
                .stream().filter(Objects::nonNull)
                .filter(item -> StringUtils.isNotBlank(item.getRoleKey()))
                .map(SysRole::getRoleKey).collect(Collectors.toList());
        //当前系统用户id
        List<Long> kindergartenIdList = Lists.newArrayList();
        if (roleKeys.contains(Constants.ADMIN_ROLE)) {
            //角色为管理员，查询所有的家长信息
            return kindergartenIdList;
        } else if (roleKeys.contains(Constants.CITY)) {
            //角色为市级角色，查询该区域下所有幼儿园下得所有班级中的家长的信息 市级
            long areaId = Objects.isNull(SecurityUtils.getLoginUser().getUser().getAreaId()) ? 0 : SecurityUtils.getLoginUser().getUser().getAreaId();
            SysArea sysArea = new SysArea();
            sysArea.setParentId(areaId);
            List<Long> sysAreaIdList = sysAreaMapper.selectSysAreaList(sysArea).stream().filter(Objects::nonNull).filter(sysAreaId -> Objects.nonNull(sysAreaId.getId())).map(SysArea::getId).collect(Collectors.toList());

            if (CollectionUtils.isNotEmpty(sysAreaIdList)) {
                //获取该区域下的所有幼儿园信息
                kindergartenIdList = classInfoMapper.getKindergartenInfoByAreaId(sysAreaIdList, null);
            }
            if (CollectionUtils.isEmpty(kindergartenIdList)) {
                return null;
            }
        } else if (roleKeys.contains(Constants.REGION_ROLE)) {
            //角色为区域角色，查询该区域下所有幼儿园下得所有班级中的家长的信息 市级
            long areaId = Objects.isNull(SecurityUtils.getLoginUser().getUser().getAreaId()) ? 0 : SecurityUtils.getLoginUser().getUser().getAreaId();

            List<Long> sysAreaIdList = new ArrayList<>();
            sysAreaIdList.add(areaId);
            if (CollectionUtils.isNotEmpty(sysAreaIdList)) {
                //获取该区域下的所有幼儿园信息
                kindergartenIdList = classInfoMapper.getKindergartenInfoByAreaId(sysAreaIdList, 3L);
            }
            if (CollectionUtils.isEmpty(kindergartenIdList)) {
                return null;
            }
        }
        return null;
    }

}
