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


import com.xinyilu.common.constant.Constants;
import com.xinyilu.common.core.domain.AjaxResult;
import com.xinyilu.common.enums.ItemCodeEnums;
import com.xinyilu.system.domain.systemarea.SysArea;
import com.xinyilu.system.domain.vo.TestItemAvgScoreVO;
import com.xinyilu.system.domain.vo.kinderPhysiqueAnalysis.CategoryTableName;
import com.xinyilu.system.domain.vo.kinderPhysiqueAnalysis.ChildrenTableName;
import com.xinyilu.system.domain.vo.testItemAvgScore.ClassAvgCategoryScoreVO;
import com.xinyilu.system.domain.vo.testItemAvgScore.TestItemAvgScoreClassVO;
import com.xinyilu.system.mapper.kindergarteninfo.KindergartenInfoMapper;
import com.xinyilu.system.mapper.systemarea.SysAreaMapper;
import com.xinyilu.system.mapper.testItemScoreinfo.TestItemScoreMapper;
import com.xinyilu.system.service.testItemAvgScoreinfo.ITestItemAvgScoreService;
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;


/**
 * @author ljh
 * @version 1.0
 * Create by 2022/8/15 15:58
 */
@Service
public class TestItemAvgScoreServiceImpl implements ITestItemAvgScoreService {

    @Resource
    private TestItemScoreMapper testItemScoreMapper;
    @Resource
    private KindergartenInfoMapper kindergartenInfoMapper;
    @Resource
    private SysAreaMapper sysAreaMapper;

    /**
     * @param classId        班级id
     * @param kindergartenId 幼儿园id
     * @param batchCode      批次编号
     * @return com.xinyilu.common.core.domain.AjaxResult
     * @date 11:40
     * @author ljh
     * @description 根据幼儿园查询某班级各项目的平均分
     **/
    @Override
    public AjaxResult selectTestItemAvgScoreList(Long classId, Long kindergartenId, String batchCode) {
        List<TestItemAvgScoreVO> dataList = Lists.newArrayList();
        TestItemAvgScoreVO testItemAvgScoreVO = new TestItemAvgScoreVO();
        // 查询每个分类的平均得分
        List<TestItemAvgScoreClassVO> testItemAvgScoreList = testItemScoreMapper.selectTestItemAvgScoreList(classId, kindergartenId, batchCode, ItemCodeEnums.BMI_CODE.getInfo());
        if (CollectionUtils.isEmpty(testItemAvgScoreList)) {
            return AjaxResult.success();
        }
        //筛选分类数据
        List<TestItemAvgScoreClassVO> testItemList = testItemAvgScoreList.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getCategoryId())).distinct().collect(Collectors.toList());
        //班级总学生数量
        Map<Long, List<TestItemAvgScoreClassVO>> studentMap = testItemAvgScoreList.stream().filter(Objects::nonNull).filter(item -> (Objects.nonNull(item.getStudentId()))).collect(Collectors.groupingBy(TestItemAvgScoreClassVO::getStudentId));
        int studentSize = studentMap.keySet().size();
        List<TestItemAvgScoreClassVO> itemAvgScoreClassList = new ArrayList<>();
        //学生信息
        Map<Long, List<TestItemAvgScoreClassVO>> categoryMap = testItemAvgScoreList.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getCategoryId())).collect(Collectors.groupingBy(TestItemAvgScoreClassVO::getCategoryId));
        categoryMap.forEach((categoryId, testItemAvgScoreClass) -> {
            TestItemAvgScoreClassVO itemAvgScoreClass = testItemAvgScoreClass.get(0);
            //每个素质的总分数
            BigDecimal testItemAvgScore = testItemAvgScoreClass.stream().filter(item -> Objects.nonNull(item.getAvgScore()))
                    .map(TestItemAvgScoreClassVO::getAvgScore)
                    .reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, BigDecimal.ROUND_HALF_UP);
            BigDecimal itemAvgScore = testItemAvgScore.divide(BigDecimal.valueOf(studentSize), 2, BigDecimal.ROUND_HALF_UP);
            itemAvgScoreClass.setAvgScore(Objects.isNull(itemAvgScore) ? BigDecimal.ZERO : itemAvgScore);
            itemAvgScoreClassList.add(itemAvgScoreClass);
        });
        ArrayList<TestItemAvgScoreClassVO> testItemSumScoreClassList = testItemList.stream().collect(Collectors.collectingAndThen(
                Collectors.toCollection(() -> new TreeSet<>(
                        Comparator.comparing(
                                TestItemAvgScoreClassVO::getTestItemId))), ArrayList::new));
        //求出平均总分数
        BigDecimal studentAvgScore = testItemSumScoreClassList.stream()
                .filter(Objects::nonNull)
                .filter(item -> Objects.nonNull(item.getAvgScore())).map(TestItemAvgScoreClassVO::getAvgScore)
                .reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, BigDecimal.ROUND_HALF_UP);
        testItemAvgScoreVO.setCategoryScoreList(itemAvgScoreClassList);
        testItemAvgScoreVO.setClassName(StringUtils.isBlank(testItemAvgScoreList.get(0).getClassName()) ? "" : testItemAvgScoreList.get(0).getClassName());
        testItemAvgScoreVO.setTotalAvScore(Objects.isNull(studentAvgScore) ? BigDecimal.ZERO : studentAvgScore);
        dataList.add(testItemAvgScoreVO);
        //设置班级类型名称
        String classTypeName = this.setClassTypeName(StringUtils.isBlank(testItemAvgScoreList.get(0).getClassType()) ? "" : testItemAvgScoreList.get(0).getClassType());
        //分类id
        List<Long> categoryIdList = testItemAvgScoreList.stream().filter(item -> Objects.nonNull(item.getCategoryId())).map(TestItemAvgScoreClassVO::getCategoryId).distinct().collect(Collectors.toList());
        //查询本园班级平均得分
        this.getKindergartenAvgScore(testItemAvgScoreList, kindergartenId, batchCode, classTypeName, dataList, categoryIdList);
        //查询全市平均得分
        this.getCityAvgScore(kindergartenId, testItemAvgScoreList, classTypeName, batchCode, categoryIdList, dataList);
        //获取表头的信息
        List<CategoryTableName> categoryTableNameList = this.setCategoryTableName(testItemList);
        ClassAvgCategoryScoreVO classAvgCategoryScoreVO = new ClassAvgCategoryScoreVO();
        classAvgCategoryScoreVO.setCategoryTableNameList(categoryTableNameList);
        classAvgCategoryScoreVO.setCategoryScoreList(dataList);
        return AjaxResult.success(classAvgCategoryScoreVO);
    }

    /**
     * 分类表头信息
     *
     * @param avgKinderCategoryScoreInfo 表头信息
     * @return List<CategoryTableName> 表头信息
     */
    private List<CategoryTableName> setCategoryTableName(List<TestItemAvgScoreClassVO> avgKinderCategoryScoreInfo) {
        Map<Long, List<TestItemAvgScoreClassVO>> tableNameMap = avgKinderCategoryScoreInfo.stream()
                .filter(item -> Objects.nonNull(item.getParentId()))
                .collect(Collectors.groupingBy(TestItemAvgScoreClassVO::getParentId));
        List<CategoryTableName> categoryTableNameList = Lists.newArrayList();
        for (Map.Entry<Long, List<TestItemAvgScoreClassVO>> tableName : tableNameMap.entrySet()) {
            CategoryTableName categoryTableName = new CategoryTableName();
            categoryTableName.setParentId(Objects.isNull(tableName.getKey()) ? 0L : tableName.getKey());
            List<TestItemAvgScoreClassVO> tableNameList = tableName.getValue();
            if (tableNameList.size() > 0) {
                categoryTableName.setParentName(tableNameList.get(0).getParentName());
            }
            List<ChildrenTableName> childrenTableNameList = tableNameList.stream().map(item -> ChildrenTableName.builder().categoryId(item.getCategoryId()).categoryName(item.getCategoryName()).build()).collect(Collectors.toList());
            categoryTableName.setChildrenTableNameList(childrenTableNameList);
            categoryTableNameList.add(categoryTableName);
        }
        return categoryTableNameList;
    }

    /**
     * 根据本机类型返回班级类型名称
     *
     * @param classType 班级类型
     * @return 班级类型名称
     */
    private String setClassTypeName(String classType) {
        String classTypeName;
        switch (classType) {
            case "LARGE_CLASS":
                classTypeName = "大班";
                break;
            case "MIDDLE_CLASS":
                classTypeName = "中班";
                break;
            case "SMALL_CLASS":
                classTypeName = "小班";
                break;
            default:
                classTypeName = "";
        }
        return classTypeName;
    }

    /**
     * 计算全园平均得分
     *
     * @param testItemAvgScoreList 测试项目分平均得分信息
     * @param kindergartenId       幼儿园id
     * @param batchCode            批次编号
     * @param classTypeName        班级类型名称
     * @param dataList             返回值数据集合
     * @param categoryIdList       分类id集合
     */
    private void getKindergartenAvgScore(List<TestItemAvgScoreClassVO> testItemAvgScoreList, Long kindergartenId, String batchCode,
                                         String classTypeName, List<TestItemAvgScoreVO> dataList, List<Long> categoryIdList) {
        // 查询本园班级平均得分
        List<TestItemAvgScoreClassVO> itemAvgScoreSchoolList = testItemScoreMapper.selectTestItemAvgScoreSchoolList(testItemAvgScoreList.get(0).getClassType(), kindergartenId, batchCode, categoryIdList, ItemCodeEnums.BMI_CODE.getInfo());
        // 得到每个项目的平均分数 进行相加得到 平均分数之和
        if (CollectionUtils.isNotEmpty(itemAvgScoreSchoolList)) {
            TestItemAvgScoreVO kinderClassAvgScoreVO = new TestItemAvgScoreVO();
            //班级总学生数量
            Map<Long, List<TestItemAvgScoreClassVO>> studentMap = itemAvgScoreSchoolList.stream().filter(Objects::nonNull).filter(item -> (Objects.nonNull(item.getStudentId()))).collect(Collectors.groupingBy(TestItemAvgScoreClassVO::getStudentId));
            int studentSize = studentMap.keySet().size();
            List<TestItemAvgScoreClassVO> itemAvgScoreClassList = new ArrayList<>();
            //学生信息
            Map<Long, List<TestItemAvgScoreClassVO>> categoryMap = itemAvgScoreSchoolList.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getCategoryId())).collect(Collectors.groupingBy(TestItemAvgScoreClassVO::getCategoryId));
            categoryMap.forEach((categoryId, testItemAvgScoreClass) -> {
                TestItemAvgScoreClassVO testItemAvgScoreClassVO = testItemAvgScoreClass.get(0);
                //每个素质的总分数
                BigDecimal testItemAvgScore = testItemAvgScoreClass.stream().filter(item -> Objects.nonNull(item.getAvgScore()))
                        .map(TestItemAvgScoreClassVO::getAvgScore)
                        .reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, BigDecimal.ROUND_HALF_UP);
                BigDecimal itemAvgScore = testItemAvgScore.divide(BigDecimal.valueOf(studentSize), 2, BigDecimal.ROUND_HALF_UP);
                testItemAvgScoreClassVO.setAvgScore(Objects.isNull(itemAvgScore) ? BigDecimal.ZERO : itemAvgScore);
                itemAvgScoreClassList.add(testItemAvgScoreClassVO);
            });
            ArrayList<TestItemAvgScoreClassVO> testItemSumScoreKindergartenList = itemAvgScoreClassList.stream().collect(Collectors.collectingAndThen(
                    Collectors.toCollection(() -> new TreeSet<>(
                            Comparator.comparing(
                                    TestItemAvgScoreClassVO::getTestItemId))), ArrayList::new));
            //本园的平均总分数
            BigDecimal studentAvgScore = testItemSumScoreKindergartenList.stream()
                    .filter(Objects::nonNull)
                    .filter(item -> Objects.nonNull(item.getAvgScore())).map(TestItemAvgScoreClassVO::getAvgScore)
                    .reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, BigDecimal.ROUND_HALF_UP);
            kinderClassAvgScoreVO.setCategoryScoreList(itemAvgScoreClassList);
            kinderClassAvgScoreVO.setClassName("本园" + classTypeName + "平均分");
            kinderClassAvgScoreVO.setTotalAvScore(Objects.isNull(studentAvgScore) ? BigDecimal.ZERO : studentAvgScore);
            dataList.add(kinderClassAvgScoreVO);
        } else {
            TestItemAvgScoreVO kinderClassAvgScoreVO = new TestItemAvgScoreVO();
            kinderClassAvgScoreVO.setClassName("本园" + classTypeName + "平均分");
            kinderClassAvgScoreVO.setTotalAvScore(BigDecimal.ZERO);
            kinderClassAvgScoreVO.setCategoryScoreList(Lists.newArrayList());
            dataList.add(kinderClassAvgScoreVO);
        }
    }

    /**
     * 计算全市平均得分
     *
     * @param kindergartenId       幼儿园id
     * @param testItemAvgScoreList 测试项目分类平均成绩信息
     * @param classTypeName        班级类型名称
     * @param batchCode            批次编号
     * @param categoryIdList       分类id集合
     * @param dataList             返回结果集
     */
    private void getCityAvgScore(Long kindergartenId, List<TestItemAvgScoreClassVO> testItemAvgScoreList, String classTypeName,
                                 String batchCode, List<Long> categoryIdList, List<TestItemAvgScoreVO> dataList) {
        List<Long> areaIdList = this.getSysAreaInfoByKindergartenId(kindergartenId);
        List<Long> kindergartenIdList = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(areaIdList)) {
            //该市下所有的幼儿园id集合
            kindergartenIdList = kindergartenInfoMapper.getKindergartenIdListByArea(areaIdList);
        }
        // 查出全市平均得分
        List<TestItemAvgScoreClassVO> testItemAvgScoreCityList = testItemScoreMapper.selectTestItemAvgScoreCityList(testItemAvgScoreList.get(0).getClassType(), kindergartenIdList, batchCode, categoryIdList, ItemCodeEnums.BMI_CODE.getInfo());
        if (CollectionUtils.isNotEmpty(testItemAvgScoreCityList)) {
            TestItemAvgScoreVO cityClassAvgScoreVO = new TestItemAvgScoreVO();
            //班级总学生数量
            Map<Long, List<TestItemAvgScoreClassVO>> studentMap = testItemAvgScoreCityList.stream().filter(Objects::nonNull).filter(item -> (Objects.nonNull(item.getStudentId()))).collect(Collectors.groupingBy(TestItemAvgScoreClassVO::getStudentId));
            int studentSize = studentMap.keySet().size();
            List<TestItemAvgScoreClassVO> itemAvgScoreClassList = new ArrayList<>();
            //学生信息
            Map<Long, List<TestItemAvgScoreClassVO>> categoryMap = testItemAvgScoreCityList.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getCategoryId())).collect(Collectors.groupingBy(TestItemAvgScoreClassVO::getCategoryId));
            categoryMap.forEach((categoryId, testItemAvgScoreClass) -> {
                TestItemAvgScoreClassVO testItemAvgScoreClassVO = testItemAvgScoreClass.get(0);
                //每个素质的总分数
                BigDecimal testItemAvgScore = testItemAvgScoreClass.stream().filter(item -> Objects.nonNull(item.getAvgScore()))
                        .map(TestItemAvgScoreClassVO::getAvgScore)
                        .reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, BigDecimal.ROUND_HALF_UP);
                BigDecimal itemAvgScore = testItemAvgScore.divide(BigDecimal.valueOf(studentSize), 2, BigDecimal.ROUND_HALF_UP);
                testItemAvgScoreClassVO.setAvgScore(Objects.isNull(itemAvgScore) ? BigDecimal.ZERO : itemAvgScore);
                itemAvgScoreClassList.add(testItemAvgScoreClassVO);
            });
            ArrayList<TestItemAvgScoreClassVO> testItemSumScoreCityList = itemAvgScoreClassList.stream().collect(Collectors.collectingAndThen(
                    Collectors.toCollection(() -> new TreeSet<>(
                            Comparator.comparing(
                                    TestItemAvgScoreClassVO::getTestItemId))), ArrayList::new));
            BigDecimal studentAvgScore = testItemSumScoreCityList.stream()
                    .filter(Objects::nonNull)
                    .filter(item -> Objects.nonNull(item.getAvgScore())).map(TestItemAvgScoreClassVO::getAvgScore)
                    .reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, BigDecimal.ROUND_HALF_UP);
            cityClassAvgScoreVO.setCategoryScoreList(itemAvgScoreClassList);
            cityClassAvgScoreVO.setClassName("全市" + classTypeName + "平均分");
            cityClassAvgScoreVO.setTotalAvScore(Objects.isNull(studentAvgScore) ? BigDecimal.ZERO : studentAvgScore);
            dataList.add(cityClassAvgScoreVO);
        } else {
            TestItemAvgScoreVO cityClassAvgScoreVO = new TestItemAvgScoreVO();
            cityClassAvgScoreVO.setClassName("全市" + classTypeName + "平均分");
            cityClassAvgScoreVO.setTotalAvScore(BigDecimal.ZERO);
            cityClassAvgScoreVO.setCategoryScoreList(Lists.newArrayList());
            dataList.add(cityClassAvgScoreVO);
        }
    }

    /**
     * 根据幼儿园id查询对应得区域信息
     *
     * @param kindergartenId 幼儿园id
     * @return 区域信息集合
     */
    private List<Long> getSysAreaInfoByKindergartenId(Long kindergartenId) {
        SysArea sysArea = kindergartenInfoMapper.getSysAreaByKindergartenId(kindergartenId);
        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 (Objects.nonNull(sysArea.getId())) {
                    sysAreaIdList.add(sysArea.getId());
                }
            }
            //所属区
            if (Constants.REGION_LEVEL.equals(sysArea.getLevel())) {
                sysAreaIdList = sysAreaMapper.getSysAreaIdList(Objects.isNull(sysArea.getParentId()) ? 0L : sysArea.getParentId());
                if (Objects.nonNull(sysArea.getParentId())) {
                    sysAreaIdList.add(sysArea.getParentId());
                }
            }
        }
        return sysAreaIdList;
    }
}
