package com.qmth.teachcloud.report.business.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.entity.SysUser;
import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
import com.qmth.teachcloud.common.service.SysOrgService;
import com.qmth.teachcloud.common.util.ExcelUtil;
import com.qmth.teachcloud.common.util.ServletUtil;
import com.qmth.teachcloud.report.business.bean.result.*;
import com.qmth.teachcloud.report.business.entity.TAExamCourse;
import com.qmth.teachcloud.report.business.entity.TAExamCourseRecord;
import com.qmth.teachcloud.report.business.entity.TBPaper;
import com.qmth.teachcloud.report.business.enums.OrderEnum;
import com.qmth.teachcloud.report.business.enums.PublishStatusEnum;
import com.qmth.teachcloud.report.business.mapper.TAExamCourseMapper;
import com.qmth.teachcloud.report.business.mapper.TAExamCourseRecordMapper;
import com.qmth.teachcloud.report.business.service.*;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

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

/**
 * <p>
 * 考试课程维度分析表 服务实现类
 * </p>
 *
 * @author wangliang
 * @since 2021-06-01
 */
@Service
public class TAExamCourseServiceImpl extends ServiceImpl<TAExamCourseMapper, TAExamCourse> implements TAExamCourseService {

    @Resource
    TAExamCourseMapper taExamCourseMapper;

    @Resource
    TAExamCourseRecordMapper taExamCourseRecordMapper;

    @Resource
    ReportCommonService reportCommonService;

    @Resource
    TBPaperService tbPaperService;

    @Resource
    SysOrgService sysOrgService;

    @Resource
    TBExamService tbExamService;

    @Resource
    TBExamStudentService tbExamStudentService;

    @Resource
    TAExamCourseService taExamCourseService;

    @Resource
    TAExamCourseCollegeTeacherService taExamCourseCollegeTeacherService;

    /**
     * 开课课程考试总览列表接口
     *
     * @param iPage
     * @param examId
     * @param semesterId
     * @param schoolId
     * @param column
     * @param order
     * @return
     */
    @Override
    public IPage<TAExamCourseResult> surveyTeacherList(IPage<Map> iPage, Long examId, Long semesterId, Long schoolId, String column, OrderEnum order) {
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        Long collegeId = sysUser.getOrgId();
        return taExamCourseMapper.surveyTeacherList(iPage, examId, semesterId, schoolId, collegeId, column, Objects.nonNull(order) ? order.name() : null);
    }


    @Override
    public ExamCourseResult getOverview(Long semesterId, Long examId, String courseCode) {
        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
        return taExamCourseMapper.getOverview(schoolId, semesterId, examId, courseCode);
    }

    /**
     * 赋分管理列表接口
     *
     * @param iPage
     * @param schoolId
     * @param examId
     * @param courseCode
     * @param publishStatus
     * @param semesterId
     * @param column
     * @param order
     * @return
     */
    @Override
    public IPage<TAExamCourseResult> surveyAspointsList(IPage<Map> iPage, Long schoolId, Long examId, String courseCode, PublishStatusEnum publishStatus, Long semesterId, String column, OrderEnum order) {
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        List<Long> collegeIds = sysOrgService.findCollegeIds(sysUser.getOrgId());
        if (Objects.nonNull(collegeIds) && collegeIds.size() > 0) {
            return taExamCourseMapper.surveyAspointsList(iPage, schoolId, examId, courseCode, Objects.nonNull(publishStatus) ? publishStatus.name() : null, semesterId, collegeIds, column, Objects.nonNull(order) ? order.name() : null);
        } else {
            return taExamCourseMapper.surveyAspointsList(iPage, schoolId, examId, courseCode, Objects.nonNull(publishStatus) ? publishStatus.name() : null, semesterId, Objects.nonNull(sysUser.getOrgId()) ? Arrays.asList(sysUser.getOrgId()) : null, column, Objects.nonNull(order) ? order.name() : null);
        }
    }

    @Override
    public GradeDistributeFinalResult getGradeDistribute(Long semesterId, Long examId, String courseCode) {
        Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        //取总体和应届平均分
        SurveyTeacherExamCourseResult surveyTeacherExamCourseResult = reportCommonService.findAvgScore(schoolId, courseCode, examId, true);
        //学院学科报表科目描述
        List<GradeDistributeResult> gradeDistributeResultList = new ArrayList<>();//全体卷面成绩
        List<GradeDistributePaperResult> gradeDistributePaperResultList = new ArrayList<>();//全体赋分成绩
        List<GradeDistributeCurrentAssignedResult> gradeDistributeCurrentAssignedResultList = new ArrayList<>();//应届赋分成绩
        List<SurveyTeacherGradeDistributionResult> surveyTeacherGradeDistributionResultList = reportCommonService.surveyTeacherDistribution(examId, courseCode, null, true);
        if (Objects.nonNull(surveyTeacherGradeDistributionResultList) && surveyTeacherGradeDistributionResultList.size() > 0) {
            for (SurveyTeacherGradeDistributionResult s : surveyTeacherGradeDistributionResultList) {
                String describe = String.join(",", s.getDescribe());
                gradeDistributeResultList.add(new GradeDistributeResult(describe, s.getAllCountRateAfter(), s.getAllCountAfter(), s.getCurrentCountAfter(), s.getCurrentCountRateAfter()));
                gradeDistributePaperResultList.add(new GradeDistributePaperResult(describe, s.getAllCountRateBefore(), s.getAllCountBefore()));
                gradeDistributeCurrentAssignedResultList.add(new GradeDistributeCurrentAssignedResult(describe, s.getCurrentCountRateAfter(), s.getCurrentCountAfter()));
            }
        }
        return new GradeDistributeFinalResult(surveyTeacherExamCourseResult, gradeDistributeResultList, gradeDistributePaperResultList, gradeDistributeCurrentAssignedResultList);
    }

    /**
     * 考查课程考试分析接口
     *
     * @param schoolId
     * @param semesterId
     * @param examId
     * @param courseCode
     * @param collegeId
     * @return
     */
    @Override
    @Cacheable(value = SystemConstant.COLLEGE_COURSE_REPORT, key = "#schoolId + '-' + #semesterId + '-' + #examId + '-' + #courseCode + '-' + #collegeId")
    public CollegeAndCourseResult surveyInspectAnalyseView(Long schoolId, Long semesterId, Long examId, String courseCode, Long collegeId) {
        //学院学科报表查询科目信息
        CourseInfoResult courseInfoResult = reportCommonService.findCourseInfo(examId, courseCode, collegeId);
        //学院学科报表科目描述
        CollegeAndSchoolGradeDistributionResult collegeAndSchoolGradeDistributionResult = reportCommonService.findCourseDistribution(examId, courseCode, collegeId);
        //学院学科报表维度查询
        DimensionAnalyzeResult dimensionAnalyzeResult = reportCommonService.findDimensionInfo(examId, courseCode, collegeId, null);
        //查找题目相关
        QuestionInfoResult questionInfoResult = reportCommonService.findSituationOfQuestions(examId, courseCode, collegeId, null);
        //查找老师得分
        TeacherInfoListResult teacherInfoListResult = reportCommonService.findTeacherInfo(examId, courseCode, collegeId);
        //查找题目信息
        QuestionListResult questionListResult = reportCommonService.findQuestionInfo(examId, courseCode, null, null, null);

        return new CollegeAndCourseResult(courseInfoResult, collegeAndSchoolGradeDistributionResult, dimensionAnalyzeResult,
                questionInfoResult, teacherInfoListResult, questionListResult);
    }

    /**
     * 开课课程考试总览图表接口
     *
     * @param schoolId
     * @param semesterId
     * @param examId
     * @param courseCode
     * @param collegeId
     * @return
     */
    @Override
    @Cacheable(value = SystemConstant.SURVEY_TEACHER_VIEW_REPORT, key = "#schoolId + '-' + #semesterId + '-' + #examId + '-' + #courseCode + '-' + #collegeId")
    public SurveyTeacherViewResult surveyTeacherView(Long schoolId, Long semesterId, Long examId, String courseCode, Long collegeId) {
        // 考试概况
        TeachCourseSurveyResult teachCourseSurveyResult = reportCommonService.getTeachCourseSurveyInfo(semesterId, examId, courseCode);

        //取总体和应届平均分
        SurveyTeacherExamCourseResult surveyTeacherExamCourseResult = reportCommonService.findAvgScore(schoolId, courseCode, examId, false);

        //学院学科报表科目描述
        List<SurveyTeacherGradeDistributionResult> surveyTeacherGradeDistributionResultList = reportCommonService.surveyTeacherDistribution(examId, courseCode, null, false);
        //查找题目信息
        QuestionListResult questionListResult = reportCommonService.findQuestionInfo(examId, courseCode, null, null, null);
        return new SurveyTeacherViewResult(surveyTeacherGradeDistributionResultList, questionListResult, surveyTeacherExamCourseResult, teachCourseSurveyResult);
    }

    /**
     * 开课课程考试总览-教师各课堂成绩排名接口
     *
     * @param iPage
     * @param schoolId
     * @param semesterId
     * @param examId
     * @param courseCode
     * @param column
     * @param order
     * @return
     */
    @Override
    public IPage<TAExamCourseCollegeTeacherResult> surveyTeacherTeacherView(IPage<Map> iPage, Long schoolId, Long semesterId, Long examId, String courseCode, String column, OrderEnum order) {
        return taExamCourseMapper.surveyTeacherTeacherView(iPage, schoolId, semesterId, examId, courseCode, column, Objects.nonNull(order) ? order.name() : null);
    }

    /**
     * 开课课程考试总览-试题难度得分情况分析接口
     *
     * @param schoolId
     * @param semesterId
     * @param examId
     * @param courseCode
     * @param collegeId
     * @param teacherId
     * @return
     */
    @Override
//    @Cacheable(value = SystemConstant.TEACHER_VIEW_REPORT, key = "#schoolId + '-' + #semester + '-' + #examId + '-' + #courseCode + '-' + #collegeId + '-' + #teacherId")
    public DimensionAnalyzeResult surveyTeacherQuestionView(Long schoolId, Long semesterId, Long examId, String courseCode, Long collegeId, Long teacherId) {
        return reportCommonService.findDimensionInfo(examId, courseCode, collegeId, teacherId);
    }

    /**
     * 开课课程考试总览-各难度水平题目上的作答分析接口
     *
     * @param schoolId
     * @param semesterId
     * @param examId
     * @param courseCode
     * @param collegeId
     * @param teacherId
     * @return
     */
    @Override
//    @Cacheable(value = SystemConstant.TEACHER_ANSWER_VIEW_REPORT, key = "#schoolId + '-' + #semester + '-' + #examId + '-' + #courseCode + '-' + #collegeId + '-' + #teacherId")
    public QuestionInfoResult surveyTeacherQuestionAnswerView(Long schoolId, Long semesterId, Long examId, String courseCode, Long collegeId, Long teacherId) {
        return reportCommonService.findSituationOfQuestions(examId, courseCode, collegeId, teacherId);
    }

    @Override
    public TrialCalculationResult trialCalculate(Long examId, String courseCode, String coefficient) {
        // 试卷分数设置
        List<TBPaper> tbPaperList = tbPaperService.list(new QueryWrapper<TBPaper>().lambda().eq(TBPaper::getExamId, examId).eq(TBPaper::getCourseCode, courseCode));
        if (tbPaperList.size() == 0) {
            throw ExceptionResultEnum.ERROR.exception("该课程不存在");
        }
        TBPaper tbPaper = tbPaperList.get(0);
        BigDecimal fullScore = tbPaper.getTotalScore();
        BigDecimal passScore = tbPaper.getPassScore();
        TrialCalculationResult trialCalculationResult = new TrialCalculationResult();
        if (coefficient.equals(SystemConstant.DEFAULT_SIGN)) {
            // 特殊赋分处理
            TAExamCourse taExamCourse = taExamCourseService.getOne(new QueryWrapper<TAExamCourse>().lambda().eq(TAExamCourse::getExamId, examId).eq(TAExamCourse::getCourseCode, courseCode));
            // 组装
            trialCalculationResult.setTotalCount(taExamCourse.getRealityCount());
            trialCalculationResult.setCurrentCount(taExamCourse.getCurrentRealityCount());
            // - 卷面-总体
            trialCalculationResult.setAvgScore(taExamCourse.getPaperAvgScore());
            trialCalculationResult.setFailRate(BigDecimal.ONE.subtract(taExamCourse.getPaperPassRate()));
            trialCalculationResult.setFailCount(taExamCourse.getRealityCount() - taExamCourse.getPaperPassCount());
            // - 卷面-应届
            trialCalculationResult.setCurrentAvgScore(taExamCourse.getPaperCurrentAvgScore());
            trialCalculationResult.setCurrentFailRate(BigDecimal.ONE.subtract(taExamCourse.getCurrentPassRate()));
            trialCalculationResult.setCurrentFailCount(taExamCourse.getRealityCount() - taExamCourse.getPaperCurrentPassCount());
            // - 赋分-总体
            trialCalculationResult.setAvgScoreAssign(taExamCourse.getAvgScore());
            trialCalculationResult.setFailRateAssign(BigDecimal.ONE.subtract(taExamCourse.getPassRate()));
            trialCalculationResult.setFailCountAssign(taExamCourse.getRealityCount() - taExamCourse.getPassCount());
            // - 赋分-应届
            trialCalculationResult.setCurrentAvgScoreAssign(taExamCourse.getCurrentAvgScore());
            trialCalculationResult.setCurrentFailRateAssign(BigDecimal.ONE.subtract(taExamCourse.getCurrentPassRate()));
            trialCalculationResult.setCurrentFailCountAssign(taExamCourse.getRealityCount() - taExamCourse.getCurrentPassCount());
        } else {
            // 参考的考生数据
            List<TAExamCourseRecord> taExamCourseRecordList = taExamCourseRecordMapper.selectList(new QueryWrapper<TAExamCourseRecord>().lambda()
                    .eq(TAExamCourseRecord::getExamId, examId)
                    .eq(TAExamCourseRecord::getCourseCode, courseCode)
                    .eq(TAExamCourseRecord::getAbsent, false));
            for (TAExamCourseRecord taExamCourseRecord : taExamCourseRecordList) {
                BigDecimal paperScore = taExamCourseRecord.getTotalScore();
                BigDecimal assignScore;
                if (!coefficient.equals(String.valueOf(0))) {
                    assignScore = paperScore.add((fullScore.subtract(paperScore)).divide(BigDecimal.valueOf(Double.parseDouble(coefficient)), 4, BigDecimal.ROUND_HALF_UP));
                    assignScore = assignScore.setScale(0, BigDecimal.ROUND_HALF_UP);
                } else {
                    assignScore = paperScore;
                }

                taExamCourseRecord.setAssignedScore(assignScore);
            }
            int totalCount = taExamCourseRecordList.size();
            int currentCount = (int) taExamCourseRecordList.stream().filter(TAExamCourseRecord::getStudentCurrent).count();

            // 查找卷面数据
            // 总体
            List<Double> paperTotalScoreList = taExamCourseRecordList.stream().map(e -> e.getTotalScore().doubleValue()).collect(Collectors.toList());
            DoubleSummaryStatistics paperTotalStatistics = paperTotalScoreList.stream().collect(Collectors.summarizingDouble(e -> e));
            double paperTotalAvgScore = paperTotalStatistics.getAverage();
            long paperTotalFailCount = paperTotalScoreList.stream().filter(e -> e < passScore.doubleValue()).count();
            BigDecimal paperTotalFailRate = BigDecimal.valueOf(paperTotalFailCount).divide(BigDecimal.valueOf(paperTotalScoreList.size()), SystemConstant.CALCULATE_SCALE, BigDecimal.ROUND_HALF_UP);

            // 应届
            List<Double> paperCurrentScoreList = taExamCourseRecordList.stream().filter(TAExamCourseRecord::getStudentCurrent).map(e -> e.getTotalScore().doubleValue()).collect(Collectors.toList());
            DoubleSummaryStatistics paperCurrentStatistics = paperCurrentScoreList.stream().collect(Collectors.summarizingDouble(e -> e));
            double paperCurrentAvgScore = paperCurrentStatistics.getAverage();
            long paperCurrentFailCount = paperCurrentScoreList.stream().filter(e -> e < passScore.doubleValue()).count();
            BigDecimal paperCurrentFailRate = BigDecimal.valueOf(paperCurrentFailCount).divide(BigDecimal.valueOf(paperCurrentScoreList.size()), SystemConstant.CALCULATE_SCALE, BigDecimal.ROUND_HALF_UP);

            // 查找赋分试算后数据
            // 总体
            List<Double> totalScoreList = taExamCourseRecordList.stream().map(e -> e.getAssignedScore().doubleValue()).collect(Collectors.toList());
            DoubleSummaryStatistics totalStatistics = totalScoreList.stream().collect(Collectors.summarizingDouble(e -> e));
            double totalAvgScore = totalStatistics.getAverage();
            long totalFailCount = totalScoreList.stream().filter(e -> e < passScore.doubleValue()).count();
            BigDecimal totalFailRate = BigDecimal.valueOf(totalFailCount).divide(BigDecimal.valueOf(totalScoreList.size()), SystemConstant.CALCULATE_SCALE, BigDecimal.ROUND_HALF_UP);

            // 应届
            List<Double> currentScoreList = taExamCourseRecordList.stream().filter(TAExamCourseRecord::getStudentCurrent).map(e -> e.getAssignedScore().doubleValue()).collect(Collectors.toList());
            DoubleSummaryStatistics currentStatistics = currentScoreList.stream().collect(Collectors.summarizingDouble(e -> e));
            double currentAvgScore = currentStatistics.getAverage();
            long currentFailCount = currentScoreList.stream().filter(e -> e < passScore.doubleValue()).count();
            BigDecimal currentFailRate = BigDecimal.valueOf(currentFailCount).divide(BigDecimal.valueOf(currentScoreList.size()), SystemConstant.CALCULATE_SCALE, BigDecimal.ROUND_HALF_UP);

            // 组装
            trialCalculationResult.setTotalCount(totalCount);
            trialCalculationResult.setCurrentCount(currentCount);
            // - 卷面-总体
            trialCalculationResult.setAvgScore(BigDecimal.valueOf(paperTotalAvgScore).setScale(1, BigDecimal.ROUND_HALF_UP));
            trialCalculationResult.setFailRate(paperTotalFailRate.setScale(SystemConstant.CALCULATE_SCALE, BigDecimal.ROUND_HALF_UP));
            trialCalculationResult.setFailCount((int) paperTotalFailCount);
            // - 卷面-应届
            trialCalculationResult.setCurrentAvgScore(BigDecimal.valueOf(paperCurrentAvgScore).setScale(1, BigDecimal.ROUND_HALF_UP));
            trialCalculationResult.setCurrentFailRate(paperCurrentFailRate.setScale(SystemConstant.CALCULATE_SCALE, BigDecimal.ROUND_HALF_UP));
            trialCalculationResult.setCurrentFailCount((int) paperCurrentFailCount);
            // - 赋分-总体
            trialCalculationResult.setAvgScoreAssign(BigDecimal.valueOf(totalAvgScore).setScale(1, BigDecimal.ROUND_HALF_UP));
            trialCalculationResult.setFailRateAssign(totalFailRate.setScale(SystemConstant.CALCULATE_SCALE, BigDecimal.ROUND_HALF_UP));
            trialCalculationResult.setFailCountAssign((int) totalFailCount);
            // - 赋分-应届
            trialCalculationResult.setCurrentAvgScoreAssign(BigDecimal.valueOf(currentAvgScore).setScale(1, BigDecimal.ROUND_HALF_UP));
            trialCalculationResult.setCurrentFailRateAssign(currentFailRate.setScale(SystemConstant.CALCULATE_SCALE, BigDecimal.ROUND_HALF_UP));
            trialCalculationResult.setCurrentFailCountAssign((int) currentFailCount);
        }
        return trialCalculationResult;
    }

    /**
     * 导出课程分析接口
     *
     * @param examId
     * @param semesterId
     * @param schoolId
     * @param courseCode
     */
    @Override
    public void courseExport(Long examId, Long semesterId, Long schoolId, String courseCode) throws Exception {
        //成绩对比明细
        IPage<TeachCollegeResult> teachCollegeResultIPage = tbExamStudentService.listTeachCollegeResult(semesterId, examId, courseCode, null, null, null, null, SystemConstant.PAGE_NUMBER, SystemConstant.PAGE_SIZE, null, null);
        //分数段
        GradeDistributeFinalResult gradeDistributeFinalResult = taExamCourseService.getGradeDistribute(semesterId, examId, courseCode);
        //各课堂应届生成绩
        IPage<TeacherClassRankResult> teacherClassRankResultIPage = taExamCourseCollegeTeacherService.listAllTeacherClassRank(semesterId, examId, null, courseCode, null, SystemConstant.PAGE_NUMBER, SystemConstant.PAGE_SIZE, null, null);

        List<String> sheetList = Arrays.asList("成绩对比明细", "全校卷面分数段", "全校最终分数段(全部)", "全校最终分数段(应届)", "各课堂应届生卷面非零平均成绩及排名");
        List<Class<?>> classList = Arrays.asList(TeachCollegeResult.class, GradeDistributePaperResult.class, GradeDistributeResult.class, GradeDistributeCurrentAssignedResult.class, TeacherClassRankResult.class);
        List<Collection<?>> collectionList = Arrays.asList(teachCollegeResultIPage.getRecords(), gradeDistributeFinalResult.getPaperGrades(), gradeDistributeFinalResult.getGrades(), gradeDistributeFinalResult.getCurrentAssignedGrades(), teacherClassRankResultIPage.getRecords());
        ExcelUtil.excelExportBatchSheet("课程分析", sheetList, classList, collectionList, ServletUtil.getResponse());
    }
}
