package com.xhkjedu.sexam.service.report;

import com.alibaba.fastjson.JSON;
import com.xhkjedu.sexam.mapper.exam.EBaseMapper;
import com.xhkjedu.sexam.mapper.paperstudent.EPaperStudentMapper;
import com.xhkjedu.sexam.mapper.report.ERbaseMapper;
import com.xhkjedu.sexam.mapper.report.EReportSchoolMapper;
import com.xhkjedu.sexam.mapper.reportclass.ERclassMapper;
import com.xhkjedu.sexam.mapper.reportclass.ERclassRankMapper;
import com.xhkjedu.sexam.mapper.reportclass.EReportClassMapper;
import com.xhkjedu.sexam.mapper.reportstu.ERstudentMapper;
import com.xhkjedu.sexam.mapper.system.UserMapper;
import com.xhkjedu.sexam.model.exam.EBase;
import com.xhkjedu.sexam.model.reportstu.ERstudent;
import com.xhkjedu.sexam.model.reportstu.ERstudentAction;
import com.xhkjedu.sexam.utils.ExamUtil;
import com.xhkjedu.sexam.vo.report.ERankParamVo;
import com.xhkjedu.sexam.vo.report.ReportParamsVo;
import com.xhkjedu.utils.N_Utils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * @author ywx
 * @className EReportClassService
 * @description 班级报告
 * @date 2022/8/8 9:46
 **/
@Service
public class EReportClassService {
    @Resource
    private EReportClassMapper eReportClassMapper;
    @Resource
    private ERstudentMapper eRstudentMapper;
    @Resource
    private ERclassMapper eRclassMapper;
    @Resource
    private ERclassRankMapper eRclassRankMapper;
    @Resource
    private EReportGenerateService eReportGenerateService;
    @Resource
    private EReportSchoolMapper eReportSchoolMapper;
    @Resource
    private EPaperStudentMapper ePaperStudentMapper;
    @Resource
    private EBaseMapper eBaseMapper;
    @Resource
    private ERbaseMapper eRbaseMapper;
    @Resource
    private UserMapper userMapper;

    //考试概况-学科成绩
    public List<Map> listXkCj(Integer examid, Integer classid) {
        return eRclassMapper.listByExamAndClassId(examid, classid);
    }

    //成绩单
    public List<Map> listCjd(ERstudent stu) {
        return eRstudentMapper.listByExamId(stu);
    }

    //成绩分析-搜索
    public List<Map> listCjFxForSearch(ERankParamVo rank) {
        List<Map> list = eRclassRankMapper.listByExamAndClassId(rank);
        if (N_Utils.isListEmpty(list)) return list;
        //结果按照科目排序
        List<String> subjectids = list.stream().map(m -> m.get("subjectid").toString()).distinct().collect(Collectors.toList());
        List<Map> subjects = eRclassRankMapper.listSubjectByIds(subjectids);
        Map<Object, Map> smap = subjects.stream().collect(Collectors.toMap(s -> s.get("subjectid"), s -> s));
        if (smap == null) smap = new HashMap<>();
        Map zf = new HashMap();
        zf.put("subjectid", "zf");
        zf.put("subjectname", "总分");
        zf.put("subjectorder", 0);
        smap.put("zf", zf);
        for (Map map : list) {
            Map s = smap.get(map.get("subjectid"));
            map.put("subjectname", s.get("subjectname"));
            map.put("subjectorder", s.get("subjectorder"));
        }
        list = list.stream().sorted(Comparator.comparing(s -> (int) s.get("subjectorder"))).collect(Collectors.toList());
        return list;
    }

    //成绩分析-设置
    @Transactional(rollbackFor = Exception.class)
    public List<Map> listCjFxForSet(ERankParamVo rank) {
        Integer examid = rank.getExamid();
        String subjectid = rank.getSubjectid();
        Integer createid = rank.getCreateid();
        Integer ranktype = rank.getRanktype();
        eReportSchoolMapper.delByExamAndSubjectId(examid, subjectid, ranktype);//删除考试等级报告
        eReportGenerateService.setSubjectRank(examid, subjectid, createid, rank.getRranks(), ranktype);//生成考试等级报告
        return eRclassRankMapper.listByExamId(rank);//考试等级报告列表
    }

    //单科概况
    public Map getDkGk(ERankParamVo rank) {
        Map map = eRclassMapper.findById(rank);//班级概况
        return map;
    }

    //单科概况-平均分
    public List<Map> listPjf(ERankParamVo rank) {
        if(rank.getShowrank() == 0) return new ArrayList<>();
        return eRclassMapper.listPjf(rank);
    }

    //单科概况-高频错题
    public List<Map> listGpCt(ERankParamVo rank) {
        List<Map> gpctList = eRclassMapper.listGpCt(rank);
        for (Map ct : gpctList) {
            //知识点
            setQuestionPoint(ct);
            ct.remove("pointjson");
        }
        return gpctList;
    }

    //试题知识点
    private void setQuestionPoint(Map ct) {
        Object pointjson = ct.get("pointjson");
        List<String> pointnames = new ArrayList<>();
        if (N_Utils.isNotEmpty(pointjson)) {
            List<Map> list = JSON.parseArray(pointjson.toString(), Map.class);
            Integer eptqid = (Integer) ct.get("eptqid");
            for (Map p : list) {
                String ques = p.get("ques").toString();
                String pointname = p.get("pointname").toString();
                List<Map> qlist = JSON.parseArray(ques, Map.class);
                for (Map q : qlist) {
                    if (N_Utils.isEmptyInteger(eptqid)) {
                        String qn = ct.get("qn").toString();
                        String[] qnList = qn.split(",");
                        List<String> qns = JSON.parseArray(q.get("qns").toString(), String.class);
                        for (String num : qnList) {
                            if (qns.contains(num)) {
                                pointnames.add(pointname);
                            }
                        }
                    } else {
                        List<Integer> eptqids = JSON.parseArray(q.get("eptqids").toString(), Integer.class);
                        if (N_Utils.numInList(eptqid, eptqids)) {
                            pointnames.add(pointname);
                        }
                    }
                }
            }
        }
        ct.put("pointnames", pointnames.stream().distinct().collect(Collectors.toList()));
    }

    //单科概况-需关注学生
    public List<Map> listGzXs(ERankParamVo rank) {
        if (rank.getShowrank() == 0) return new ArrayList<>();
        return eRclassMapper.listGzXs(rank);
    }

    //试卷概况
    public Map listSjGk(ERankParamVo rank) {
        Map paper = eReportClassMapper.getPaperByExamSubjectId(rank);
        Integer ptype = (Integer) paper.get("ptype");
        List<Map> list;
        if (ptype == 1) {
            list = eReportClassMapper.listTkSjGk(rank);
            List<Map> questions = eReportClassMapper.listTkQuestion((Integer) paper.get("epid"));
            Object pointjson = paper.get("pointjson");
            for (Map q : list) {
                q.put("pointjson", pointjson);
                setQuestionPoint(q);//试题知识点
                Object questionid = q.get("questionid");
                Map qmap;
                if (N_Utils.isEmpty(q.get("eptqid"))) {
                    qmap = questions.stream().filter(tq -> questionid.equals(tq.get("mquestionid"))).findFirst().orElse(null);
                    q.put("ctype", qmap.get("mctype"));
                    q.put("qtypename", qmap.get("mqtypename"));
                    q.put("qstem", qmap.get("mqstem"));
                    q.put("qanalyze", qmap.get("mqanalyze"));
                    q.put("hashear", qmap.get("mhashear"));
                    q.put("hearfile", qmap.get("mhearfile"));
                    List<Map> sonques = questions.stream().filter(tq -> questionid.equals(tq.get("questionpid")))
                            .collect(Collectors.toList());
                    sonques.forEach(sq -> {
                        sq.remove("mctype");
                        sq.remove("mqtypename");
                        sq.remove("mqstem");
                        sq.remove("mqanalyze");
                        sq.remove("mhashear");
                        sq.remove("mhearfile");
                        sq.remove("hashear");
                        sq.remove("hearfile");
                    });
                    q.put("sonques", sonques);
                } else {
                    qmap = questions.stream().filter(tq -> questionid.equals(tq.get("questionid")))
                            .findFirst().orElse(null);
                    q.put("ctype", qmap.get("ctype"));
                    q.put("score", qmap.get("score"));
                    q.put("answer", qmap.get("answer"));
                    q.put("qtypename", qmap.get("qtypename"));
                    q.put("qstem", qmap.get("qstem"));
                    q.put("qoption", qmap.get("qoption"));
                    q.put("qanalyze", qmap.get("qanalyze"));
                    q.put("hashear", qmap.get("hashear"));
                    q.put("hearfile", qmap.get("hearfile"));
                    q.put("qn", qmap.get("qn"));
                    q.put("qorder", qmap.get("qorder"));
                }
            }
        } else {
            String examname = paper.get("examname").toString();
            list = eReportClassMapper.listFjSjGk(rank);
            for (Map q : list) {
                q.put("qstem", examname + "-第" + q.get("qn") + "题");
            }
        }
        paper.remove("examname");
        paper.remove("pointjson");
        paper.put("questions", list);
        return paper;
    }

    //试卷分析
    public Map getSjFx(ERankParamVo rank) {
        Map map = new HashMap();
        List<Map> types = eReportClassMapper.listType(rank);//大题分析
        List<Map> questions = eReportClassMapper.listQuestion(rank);//小题分析
        List<Map> points = eReportClassMapper.listPoint(rank);//知识点分析
        map.put("types", types);
        map.put("questions", questions);
        map.put("points", points);
        return map;
    }

    //行为分析-科目
    public List<Map> listXwKm(ERstudentAction rank) {
        String subjectjson = eReportClassMapper.getSubjectJson(rank);
        if(N_Utils.isEmpty(subjectjson)) return new ArrayList<>();
        List<Map> list = JSON.parseArray(subjectjson, Map.class);
        String subjectid = rank.getSubjectid();
        if (N_Utils.isNotEmpty(subjectid) && N_Utils.isListNotEmpty(list)) {
            return list.stream().filter(s -> subjectid.equals(s.get("subjectid").toString()))
                    .collect(Collectors.toList());
        } else {
            return list;
        }
    }

    //行为分析-学生
    public List<Map> listXwXs(ERstudentAction rank) {
        return eReportClassMapper.listXwXs(rank);
    }

    //优秀试卷分析-详情
    public Map getSjXq(ERankParamVo rank) {
        Map map = eReportClassMapper.getStuPaperInfo(rank);//学生试卷基础信息
        List<Map> types;//试题详情
        Integer ptype = (Integer) map.get("ptype");
        Integer epsid = (Integer) map.get("epsid");
        if (ptype == 1) {
            //题库试卷试题
            types = ePaperStudentMapper.listStuPaperQuestionsForBg(epsid);
            for (Map qt : types) {
                List<Map> questions = new ArrayList<>();
                List<Map> questionList = (List<Map>) qt.get("questions");
                List<Object> qorders = questionList.stream().map(q -> q.get("qorder")).distinct().collect(Collectors.toList());
                for (Object qorder : qorders) {
                    Map q = questionList.stream().filter(tq -> tq.get("qorder").equals(qorder))
                            .findFirst().orElse(null);
                    Map qmap = new HashMap();
                    qmap.put("qn", q.get("qn"));
                    qmap.put("qorder", q.get("qorder"));
                    if (!"1".equals(q.get("qlevel").toString())) {//复合题
                        String questionpid = q.get("questionpid").toString();
                        qmap.put("ctype", q.get("mctype"));
                        qmap.put("qstem", q.get("mqstem"));
                        qmap.put("qanalyze", q.get("mqanalyze"));
                        qmap.put("hashear", q.get("mhashear"));
                        qmap.put("hearfile", q.get("mhearfile"));
                        double mqscore = 0;
                        List<Map> ztList = questionList.stream().filter(
                                tq -> questionpid.equals(tq.get("questionpid"))).collect(Collectors.toList());
                        List<Map> sonques = new ArrayList<>();
                        Integer good = 0;//优秀试卷0默认1优秀
                        Integer bad = 0;//违纪试卷0默认1违纪
                        for (Map q2 : ztList) {
                            Map zt = new HashMap();
                            zt.put("ctype", q2.get("ctype"));
                            double qscore = (double) q2.get("qscore");
                            mqscore = ExamUtil.add(mqscore, qscore);
                            zt.put("qscore", qscore);
                            zt.put("answer", q2.get("answer"));
                            zt.put("qstem", q2.get("qstem"));
                            zt.put("qoption", q2.get("qoption"));
                            zt.put("qanalyze", q2.get("qanalyze"));
                            zt.put("stuscore", q2.get("stuscore"));
                            zt.put("answertype", q2.get("answertype"));
                            zt.put("stuanswer", q2.get("stuanswer"));
                            zt.put("stuanswertxt", q2.get("stuanswertxt"));
                            zt.put("qn", q2.get("qn"));
                            zt.put("qorder", q2.get("sorder"));
                            zt.put("answered", q2.get("answered"));
                            zt.put("good", q2.get("good"));
                            zt.put("bad", q2.get("bad"));
                            if (q2.get("good").equals(1)) {
                                good = 1;
                            }
                            if (q2.get("bad").equals(1)) {
                                bad = 1;
                            }
                            sonques.add(zt);
                        }
                        qmap.put("good", good);
                        qmap.put("bad", bad);
                        qmap.put("qscore", mqscore);
                        qmap.put("sonques", sonques);
                    } else {//简单题
                        qmap.put("ctype", q.get("ctype"));
                        qmap.put("qscore", q.get("qscore"));
                        qmap.put("answer", q.get("answer"));
                        qmap.put("qstem", q.get("qstem"));
                        qmap.put("qoption", q.get("qoption"));
                        qmap.put("stuscore", q.get("stuscore"));
                        qmap.put("answertype", q.get("answertype"));
                        qmap.put("stuanswer", q.get("stuanswer"));
                        qmap.put("stuanswertxt", q.get("stuanswertxt"));
                        qmap.put("qanalyze", q.get("qanalyze"));
                        qmap.put("hashear", q.get("hashear"));
                        qmap.put("hearfile", q.get("hearfile"));
                        qmap.put("answered", q.get("answered"));
                        qmap.put("good", q.get("good"));
                        qmap.put("bad", q.get("bad"));
                    }
                    questions.add(qmap);
                }
                qt.put("questions", questions);
            }
        } else {
            types = ePaperStudentMapper.listStuPaperFjQuestionsForBg(epsid);
        }
        map.put("types", types);
        return map;
    }

    //单科概况-等级统计
    public List<Map> listDkGkDjTj(ERankParamVo rank) {
        if (rank.getShowrank() != 3) return new ArrayList<>();
        return eRclassRankMapper.listDkGkDjTj(rank);
    }

    //试卷概况-优秀卷
    public List<Map> listSjGkYxj(ERankParamVo rank) {
        return eReportClassMapper.listSjGkYxj(rank);
    }

    //班级报告列表--教师权限班级考试列表
    public List<Map> listEndExamsForClassTeacher(ReportParamsVo paramsVo){
        return eReportClassMapper.listEndExamsForClassTeacher(paramsVo);
    }

    //考试班级--教师权限下
    public List<Map> listExamQxClassTeacher(ReportParamsVo paramsVo){
        Integer schoolid = userMapper.getSchoolidByUserid(paramsVo.getTeacherid());
        paramsVo.setSchoolid(schoolid);
        return eReportClassMapper.listExamClass(paramsVo.getExamid(), paramsVo.getTeacherid(),paramsVo.getSchoolid());
    }

    //教师考试权限科目
    public List<Map> listExamSubject(Integer examid, Integer teacherid) {
        return eReportClassMapper.listExamSubject(examid, teacherid);
    }

    //班级报告教师成绩单
    public List<Map> listTeacherCjd(ERstudent stu) {
        List<Map> list = eRstudentMapper.listTeacherCjd(stu);
        String classname = eReportClassMapper.getClassNameByExamIdCid(stu.getExamid(),stu.getClassid());
        list.forEach(l->l.put("classname", classname));
        return list;
    }

    //获取考试基本信息（科目、班级、班级下学生）
    public Map getExamSubjectClass(Integer examid, Integer teacherid) {
        Map map = eBaseMapper.findById(examid);
        List<Map> subjects = eReportClassMapper.listExamSubject(examid, teacherid);
        map.put("subjects", subjects);
        Integer schoolid = userMapper.getSchoolidByUserid(teacherid);
        List<Map> classes = eReportClassMapper.listExamClass(examid, teacherid,schoolid);
        map.put("classes", classes);
        return map;
    }

    //班级报告列表-班主任
    public List<Map> listEndExamsForClass(ReportParamsVo paramsVo) {
        return eReportClassMapper.listEndExamsForClass(paramsVo);
    }

    //获取教师显示排名得分
    public Integer getShowRank(Integer examid) {
        EBase base = eBaseMapper.getShowRankById(examid);
        return base.getTeashowrank();
    }

    //pdf报告-考试概况
    public Map getPdfKsGk(Integer examid) {
        Map map = eRbaseMapper.findByExamId(examid);
        map.put("stunum", (Integer) map.get("stunum") - (Integer) map.get("missnum"));
        Map base = eBaseMapper.findById2(examid);
        map.putAll(base);
        return map;
    }

    //pdf报告-科目概况
    public List<Map> listKmGg(ERankParamVo rank) {
        List<Map> subjects = eRclassMapper.listByExamIdClassId(rank);
        for (Map subject : subjects) {
            getDkgk(rank, subject);
        }
        return subjects;
    }

    //pdf报告-单科概况
    @Async("asyncPoolTaskExecutor")
    public void getDkgk(ERankParamVo rank, Map subject) {
        rank.setSubjectid(subject.get("subjectid").toString());
        subject.put("pjf", listPjf(rank));//平均分
        subject.put("djtj", listDkGkDjTj(rank));//成绩等级分布
        rank.setRanktype(1);
        subject.put("dfjb", listGzXs(rank));//大幅进步学生
        rank.setRanktype(2);
        subject.put("dftb", listGzXs(rank));//大幅退步学生
        rank.setRanktype(3);
        subject.put("ljs", listGzXs(rank));//临界生
        rank.setRanktype(4);
        subject.put("bds", listGzXs(rank));//波动生
        subject.put("gpctList", listGpCt(rank));//高频错题

        subject.put("types", eReportClassMapper.listType(rank));//大题分析
        subject.put("questions", eReportClassMapper.listQuestion(rank));//小题分析
        subject.put("points", eReportClassMapper.listPoint(rank));//知识点分析
    }

    //班级报告-获取pdf报告状态和班级pdf地址
    public Map getReportClass(Integer examid,Integer classid){
        return eRclassMapper.getReportClass(examid,classid);
    }

    //获取考试班级名称
    public String getClassName(Integer examid, Integer classid) {
        return eReportClassMapper.getClassName(examid,classid);
    }

    //获取考试PDF报告基础信息
    public Map getPdfInfo(Integer examid, Integer classid) {
        return eReportClassMapper.getPdfInfo(examid, classid);
    }

    //单科考试概况
    public Map getDkKsGk(ERankParamVo rank) {
        return eReportClassMapper.getDkKsGk(rank);
    }

    //获取单科考试PDF报告基础信息
    public Map getPdfDkInfo(Integer examid, Integer classid, String subjectid) {
        return eReportClassMapper.getPdfDkInfo(examid, classid, subjectid);
    }

    //单科报告-获取pdf报告状态和地址
    public Map getReportDkClass(Integer examid, Integer classid, String subjectid) {
        return eReportClassMapper.getReportDkClass(examid, classid, subjectid);
    }

    //获取教师学校id
    public Integer getSchoolidByUserid(Integer userid){
        return userMapper.getSchoolidByUserid(userid);
    }
}
