package com.xhkjedu.smarking.service.report.generate;

import com.alibaba.fastjson.JSON;
import com.xhkjedu.smarking.mapper.report.reportsubject.MsrSubjectClassMapper;
import com.xhkjedu.smarking.mapper.report.reportsubject.MsrSubjectMapper;
import com.xhkjedu.smarking.mapper.stupaper.MsPaperStudentQuestionMapper;
import com.xhkjedu.smarking.model.paper.MsPaper;
import com.xhkjedu.smarking.model.report.reportother.MsrReportparam;
import com.xhkjedu.smarking.model.report.reportstu.MsrStudent;
import com.xhkjedu.smarking.model.report.reportsubject.MsrSubject;
import com.xhkjedu.smarking.model.report.reportsubject.MsrSubjectClass;
import com.xhkjedu.smarking.service.report.reportother.MsrReportparamService;
import com.xhkjedu.smarking.utils.MarkingUtil;
import com.xhkjedu.smarking.vo.paper.SQScoreVo;
import com.xhkjedu.smarking.vo.paper.SQuestionVo;
import com.xhkjedu.smarking.vo.report.reportother.RankGroupVo;
import com.xhkjedu.smarking.vo.report.reportother.SzJsonVo;
import com.xhkjedu.utils.N_Utils;
import org.springframework.stereotype.Service;

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

/**
 *@Description 科目生成报告服务
 *@Author ywx
 *Date 2025/1/3 11:08
 **/
@Service
public class ReportGenerateSubjectService {
    @Resource
    private MsPaperStudentQuestionMapper paperStudentQuestionMapper;
    @Resource
    private MsrSubjectMapper msrSubjectMapper;
    @Resource
    private MsrSubjectClassMapper msrSubjectClassMapper;
    @Resource
    private MsrReportparamService msrReportparamService;

    //保存科目分析
    public Map<String, MsrSubject> saveSubject(Integer examid, List<MsrStudent> paperStudents
            , List<MsPaper> subjects, List<Integer> mpids) {
        double fullscore = subjects.stream().mapToDouble(MsPaper::getPscore).sum();
        String subjectid;
        //科目分析
        Map<String, MsrSubject> subjectMap = new HashMap<>();//科目分析map
        List<MsrSubject> msrSubjects = new ArrayList<>();
        MsrSubject msrSubject = new MsrSubject();
        msrSubject.setExamid(examid);
        subjectid = "zf";
        msrSubject.setSubjectid(subjectid);
        msrSubject.setSubjectname("总分");
        msrSubject.setFullscore(fullscore);
        Map<Integer, List<MsrStudent>> collect = paperStudents.stream().collect(Collectors.groupingBy(MsrStudent::getStudentid));
        List<MsrStudent> studentList = new ArrayList<>();
        for (Map.Entry<Integer, List<MsrStudent>> entry : collect.entrySet()) {
            MsrStudent student = new MsrStudent();
            student.setStudentid(entry.getKey());
            Double stuscore = N_Utils.formatDouble(entry.getValue().stream().mapToDouble(MsrStudent::getStuscore).sum(), 1);
            student.setStuscore(stuscore);
            student.setScorerate(N_Utils.getDoubleDivideAndMulitiply(stuscore, fullscore));
            int sstate = 0;
            long count = entry.getValue().stream().filter(s -> s.getSstate().equals(2)).count();
            if (count > 0) {
                sstate = 2;
            }
            student.setSstate(sstate);
            studentList.add(student);
        }
        List<SQScoreVo> questionScores = paperStudentQuestionMapper.listByMpIds(mpids);//获取参与统计科目单题得分情况
        List<Double> zfmtfc = new ArrayList<>();
        Map<String, List<Double>> dkMtfc = new HashMap<>();
        for (SQScoreVo s : questionScores) {
            List<Double> mtfc = new ArrayList<>();
            List<SQuestionVo> questions = s.getQuestions();
            for (SQuestionVo question : questions) {
                double fc = MarkingUtil.fc(question.getStuscores());
                zfmtfc.add(fc);
                mtfc.add(fc);
            }
            dkMtfc.put(s.getSubjectid(), mtfc);
        }
        msrSubject.setMtfc(zfmtfc);
        setSubject(msrSubject, studentList);
        msrSubjects.add(msrSubject);
        subjectMap.put(subjectid, msrSubject);
        for (MsrStudent student : paperStudents) {
            student.setScorerate(N_Utils.getDoubleDivideAndMulitiply(student.getStuscore(), student.getFullscore()));
        }
        Map<String, List<MsrStudent>> subjectCollect = paperStudents.stream().collect(Collectors.groupingBy(MsrStudent::getSubjectid));
        for (MsPaper subject : subjects) {
            subjectid = subject.getSubjectid();
            msrSubject = new MsrSubject();
            msrSubject.setExamid(examid);
            msrSubject.setSubjectid(subjectid);
            msrSubject.setSubjectname(subject.getSubjectname());
            msrSubject.setFullscore(subject.getPscore());
            studentList = subjectCollect.get(subjectid);
            msrSubject.setMtfc(dkMtfc.get(subjectid));
            setSubject(msrSubject, studentList);
            msrSubjects.add(msrSubject);
            subjectMap.put(subjectid, msrSubject);
        }
        List<Double> avgScores = msrSubjects.stream().map(MsrSubject::getAvgscore).sorted().collect(Collectors.toList());
        Map<Double, Integer> fspm = MarkingUtil.fspm(avgScores);//平均分排名
        for (MsrSubject subject : msrSubjects) {
            subject.setAvgrank(fspm.get(subject.getAvgscore()));
            subject.setAvgrankrate(MarkingUtil.div(subject.getAvgrank(), subject.getTotalnum()));
            String subjectid1 = subject.getSubjectid();
            int pnum;//试卷中的题目总数
            if ("zf".equals(subjectid1)) {
                pnum = subjects.stream().mapToInt(MsPaper::getPnum).sum();
            } else {
                pnum = subjects.stream().filter(s -> s.getSubjectid().equals(subjectid1)).findFirst().get().getPnum();
            }
            subject.setAxdxs(MarkingUtil.axdxs(pnum, subject.getMtfc(), subject.getZffc()));
        }
        msrSubjectMapper.insertList(msrSubjects);
        return subjectMap;
    }

    //设置科目分析计算参数
    private void setSubject(MsrSubject msrSubject, List<MsrStudent> studentList) {
        List<MsrStudent> studentList2 = studentList.stream().filter(s -> s.getSstate().equals(2)).collect(Collectors.toList());//参与统计学生列表
        int totalnum = studentList.size();
        int stunum = studentList2.size();
        int missnum = totalnum - stunum;
        msrSubject.setTotalnum(totalnum);
        msrSubject.setStunum(stunum);
        msrSubject.setNumrate(N_Utils.getIntegerDivideAndMulitiply(stunum, totalnum));
        msrSubject.setMissnum(missnum);
        DoubleSummaryStatistics subjectStatistics = studentList2.stream().mapToDouble(MsrStudent::getStuscore).summaryStatistics();
        double subjectStatisticsMax = N_Utils.handleInfinity(subjectStatistics.getMax());
        //最低分均不包括0分
        double subjectStatisticsMin = N_Utils.handleInfinity(subjectStatistics.getMin());
        double subjectStatisticsAverage = N_Utils.formatDouble(subjectStatistics.getAverage(), 2);
        msrSubject.setMaxscore(subjectStatisticsMax);
        msrSubject.setMinscore(subjectStatisticsMin);
        msrSubject.setAvgscore(subjectStatisticsAverage);
        Double avgscore = msrSubject.getAvgscore();
        Double fullscore = msrSubject.getFullscore();
        msrSubject.setScorerate(N_Utils.getDoubleDivideAndMulitiply(avgscore, fullscore));
        List<Double> scores = studentList.stream().map(MsrStudent::getStuscore).sorted().collect(Collectors.toList());
        double bzc = MarkingUtil.bzc(scores);
        msrSubject.setBzc(bzc);
        msrSubject.setZffc(MarkingUtil.fc(scores));
        msrSubject.setCyxs(N_Utils.getDoubleDivideAndMulitiply(bzc, avgscore));
        msrSubject.setNd(MarkingUtil.div(avgscore, fullscore));
        msrSubject.setQfd(MarkingUtil.qfd(scores));
        List<Double> scoreRates = studentList.stream().map(MsrStudent::getScorerate).sorted().collect(Collectors.toList());
        double dfllc = MarkingUtil.sub(scoreRates.get(scoreRates.size() - 1), scoreRates.get(0));
        msrSubject.setDfllc(dfllc);
        msrSubject.setDflxdlc(MarkingUtil.div(dfllc, msrSubject.getScorerate()));
        msrSubject.setEsscore(MarkingUtil.cynjdf(scores, 0.2));
        msrSubject.setSsscore(MarkingUtil.cynjdf(scores, 0.4));
        msrSubject.setLsscore(MarkingUtil.cynjdf(scores, 0.6));
        msrSubject.setBsscore(MarkingUtil.cynjdf(scores, 0.8));
    }

    //科目班级分数分布区间分析
    public void saveSubjectClass(Integer examid, List<MsrStudent> msrStudents,Integer raid) {
        Map<String, SzJsonVo> qjMap = new HashMap<>();
        List<MsrReportparam> params = msrReportparamService.getMsrReportParams(examid, "scoresection", "xk");
        for (MsrReportparam param : params) {
            qjMap.put(param.getSubjectid(), JSON.parseObject(param.getSzjson(), SzJsonVo.class));
        }
        List<MsrSubjectClass> msrSubjectClasses = new ArrayList<>();//科目班级分数分布区间分析
        Map<String, List<MsrStudent>> collect = MarkingUtil.getSubjectCollect(msrStudents);
        Map<String, Integer> rsMap = new HashMap<>();//学科人数map
        for (Map.Entry<String, List<MsrStudent>> entry : collect.entrySet()) {
            MarkingUtil.studentsDistinct(entry, rsMap);
        }
        setSubjectClass(examid, collect, qjMap, msrSubjectClasses, rsMap,raid);
        Map<String, List<MsrStudent>> scCollect = msrStudents.stream().collect(Collectors.groupingBy(s -> s.getClassid() + "_" + s.getSubjectid()));
        setSubjectClass(examid, scCollect, qjMap, msrSubjectClasses, rsMap,raid);
        msrSubjectClassMapper.insertList(msrSubjectClasses);
    }

    //科目班级分数分布区间计算
    private void setSubjectClass(Integer examid, Map<String, List<MsrStudent>> scCollect, Map<String, SzJsonVo> qjMap
            , List<MsrSubjectClass> msrSubjectClasses, Map<String, Integer> rsMap,Integer raid) {
        Integer totalnum;
        String subjectid;
        for (Map.Entry<String, List<MsrStudent>> entry : scCollect.entrySet()) {
            String key = entry.getKey();
            Integer classid = N_Utils.obj2Int(key.split("_")[0]);
            subjectid = key.split("_")[1];
            SzJsonVo vo = qjMap.get(subjectid);
            List<MsrStudent> studentList = entry.getValue();
            totalnum = rsMap.get(subjectid);//科目总人数
            Double fullscore = studentList.get(0).getFullscore();
            List<RankGroupVo> fdScore = MarkingUtil.fdScore(fullscore, N_Utils.obj2Int(vo.getDjvalue()));
            for (RankGroupVo rg : fdScore) {
                int minscore = rg.getMinvalue();
                int maxscore = rg.getMaxvalue();
                String qjname = rg.getGroupname();
                double min = MarkingUtil.objToDouble(minscore);
                double max = MarkingUtil.objToDouble(maxscore);
                List<MsrStudent> qjstudents;
                if (fullscore.compareTo(max) == 0) {
                    qjstudents = studentList.stream().filter(s -> s.getStuscore().compareTo(min) >= 0).collect(Collectors.toList());
                } else {
                    qjstudents = studentList.stream().filter(s -> s.getStuscore().compareTo(min) >= 0 && s.getStuscore().compareTo(max) < 0).collect(Collectors.toList());
                }
                int qjnum = qjstudents.size();
                MsrSubjectClass msrSubjectClass = new MsrSubjectClass();
                msrSubjectClass.setRaid(raid);
                msrSubjectClass.setExamid(examid);
                msrSubjectClass.setSubjectid(subjectid);
                msrSubjectClass.setClassid(classid);
                msrSubjectClass.setQjname(qjname);
                msrSubjectClass.setQjnum(qjnum);
                msrSubjectClass.setQjrate(N_Utils.getIntegerDivideAndMulitiply(qjnum, totalnum));
                double qjavg = qjstudents.stream().mapToDouble(MsrStudent::getStuscore).summaryStatistics().getAverage();
                msrSubjectClass.setQjavgrate(N_Utils.getDoubleDivideAndMulitiply(qjavg, fullscore));
                String stuids = qjstudents.stream().map(s -> s.getStudentid().toString()).collect(Collectors.joining(","));
                msrSubjectClass.setStuids(stuids);
                msrSubjectClasses.add(msrSubjectClass);
            }
        }
    }

}
