package com.xhkjedu.sstudy.service.paperstudent;

import com.alibaba.fastjson.JSON;
import com.xhkjedu.sstudy.mapper.paper.PaperMapper;
import com.xhkjedu.sstudy.mapper.paper.PaperQtypeQuestionMapper;
import com.xhkjedu.sstudy.mapper.paper.PaperScantronMapper;
import com.xhkjedu.sstudy.mapper.paperstudent.PaperClassMapper;
import com.xhkjedu.sstudy.mapper.paperstudent.PaperStudentMapper;
import com.xhkjedu.sstudy.mapper.paperstudent.PaperStudentQuestionMapper;
import com.xhkjedu.sstudy.mapper.paperstudent.PaperStudentScantronMapper;
import com.xhkjedu.sstudy.mapper.system.SchoolMapper;
import com.xhkjedu.sstudy.model.paper.TPaper;
import com.xhkjedu.sstudy.model.paper.TPaperQtypeQuestion;
import com.xhkjedu.sstudy.model.paper.TPaperScantron;
import com.xhkjedu.sstudy.model.paperstudent.TPaperClass;
import com.xhkjedu.sstudy.model.paperstudent.TPaperStudent;
import com.xhkjedu.sstudy.model.paperstudent.TPaperStudentQuestion;
import com.xhkjedu.sstudy.model.paperstudent.TPaperStudentScantron;
import com.xhkjedu.sstudy.utils.ArithUtil;
import com.xhkjedu.sstudy.vo.paperstudent.PaperClassParam;
import com.xhkjedu.sstudy.vo.paperstudent.PaperGroupParam;
import com.xhkjedu.sstudy.vo.paperstudent.PaperStudentParam;
import com.xhkjedu.sstudy.vo.question.QuestionVo;
import com.xhkjedu.sstudy.vo.subjectbook.PointVo;
import com.xhkjedu.utils.N_Utils;
import com.xhkjedu.vo.ResultVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

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

/**
 * @ClassName PaperGroupService
 * Description 作业--班级
 * Author WN
 * Date 2020/6/9 11:03
 **/
@Slf4j
@Service
public class PaperClassService {
    @Autowired
    private PaperClassMapper paperClassMapper;
    @Autowired
    private PaperMapper paperMapper;
    @Autowired
    private PaperStudentMapper paperStudentMapper;

    @Autowired
    private PaperQtypeQuestionMapper paperQtypeQuestionMapper;
    @Autowired
    private PaperScantronMapper paperScantronMapper;
    @Resource
    private PaperStudentQuestionMapper paperStudentQuestionMapper;
    @Resource
    private PaperStudentScantronMapper paperStudentScantronMapper;
    @Resource
    private SchoolMapper schoolMapper;

    //处理作业分组数据（附件）
    private Integer setPaperGroup(Integer stunum
            , List<TPaperScantron> pquestions, Integer timestamp, Integer schoolid
            , Integer paperid, Integer starttime, Integer stoptime, Integer showtype, Integer createid
            , Integer papernum, Double paperscore, Integer classid, List<PaperStudentParam> students, Integer hasfc) {
        List<TPaperStudentScantron> savestuque=new ArrayList<>();
        if (N_Utils.isListNotEmpty(students)) {
            TPaperClass pg = new TPaperClass();
            pg.setPaperid(paperid);
            pg.setClassid(classid);
            pg.setPgstate(22);
            pg.setStarttime(starttime);
            pg.setStoptime(stoptime);
            pg.setShowtype(showtype);
            pg.setCreateid(createid);
            pg.setSchoolid(schoolid);
            pg.setCreatetime(timestamp);
            pg.setChecked(0);
            pg.setHasfc(hasfc);
            paperClassMapper.insertSelective(pg);

            //根据studentid集合去重
            List<PaperStudentParam> students2 = students.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(PaperStudentParam::getStudentid))), ArrayList::new));
            for (PaperStudentParam s : students2) {
                TPaperStudent ps = new TPaperStudent();
                ps.setPaperid(paperid);
                ps.setClassid(classid);
                ps.setStudentid(s.getStudentid());
                ps.setCreateid(createid);
                ps.setCreatetime(N_Utils.getSecondTimestamp());
                ps.setSchoolid(schoolid);
                ps.setPapernum(papernum);
                ps.setPaperscore(paperscore);
                Integer psid = savePaperStu(ps);
                for (TPaperScantron q : pquestions) {
                    TPaperStudentScantron sq=new TPaperStudentScantron();
                    sq.setPaperid(paperid);
                    sq.setClassid(classid);
                    sq.setStudentid(s.getStudentid());
                    sq.setPsid(psid);
                    sq.setPscaid(q.getPscaid());
                    sq.setQscore(q.getPsscore());
                    sq.setQn(q.getQn());
                    sq.setQorder(q.getPsorder());
                    sq.setSchoolid(schoolid);
                    savestuque.add(sq);
                }
                stunum += 1;
            }
            if(N_Utils.isListNotEmpty(savestuque)) paperStudentScantronMapper.saveBatchStudentScantron(savestuque);
        }
        return stunum;
    }

    /**
     * 获取参与作业学生列表
     *
     * @return java.util.List<com.xhkjedu.vo.paperstudent.PaperGroupVo>
     * @Param [paperid]
     * @Author ywx
     * @Date 2020/7/24 14:52
     **/
    public List<Map> listPaperStudent(Integer paperid, Integer schoolid) {
        return paperClassMapper.listPaperStudent(paperid, schoolid);
    }

    /**
     * 获取发布对象
     *
     * @return java.util.List<java.util.Map>
     * @Param [paperid, createid, papertype]
     * @Author ywx
     * @Date 2022/7/1 10:28
     **/
    public Map listObject(Integer paperid, Integer createid, Integer papertype, Integer schoolid) {
        Map paper = new HashMap();
        List<Map> groups = paperClassMapper.listGroupByTeacherId(createid, schoolid);//教师权限分组
        //20230217过滤无学生分组，出现groupnum大于0，但是实际关联表没有学生
        groups = groups.stream().filter(m -> m.get("studentid") != null).collect(Collectors.toList());

        Map<Integer, List<Map>> classList = groups.stream().collect(Collectors.groupingBy(m -> (Integer) m.get("classid")
                , LinkedHashMap::new, Collectors.toList()));
        List<Integer> studentids = groups.stream().map(m -> (Integer) m.get("studentid")).distinct().collect(Collectors.toList());

        List<Map> classes = new ArrayList<>();

        if(N_Utils.isListNotEmpty(studentids)){
            List<Map> users = paperClassMapper.listUserByIds(studentids);
            Map<Integer, Map> userMap = users.stream().collect(Collectors.toMap(m -> (Integer) m.get("userid"), m -> m));
            if (papertype == 3) {//靶向作业
                List<QuestionVo> questions = paperClassMapper.listPaperQuestions(paperid);
                for (QuestionVo question : questions) {
                    String qstemtxt = question.getQstemtxt();
                    if(N_Utils.isNotEmpty(qstemtxt)){
                        List<Map> sonqlist=JSON.parseArray(qstemtxt, Map.class);
                        question.setSonqlist(sonqlist);
                    }
                    question.setQstemtxt(null);
                    List<PointVo> points = JSON.parseArray(question.getSource(), PointVo.class);
                    question.setPoints(points);
                    question.setSource(null);
                }
                paper.put("questions", questions);
                List<String> questionids = questions.stream().map(QuestionVo::getQuestionid).collect(Collectors.toList());
                List<Map> stuQuestions = paperClassMapper.listStuQuestion(questionids, studentids);
                for (Integer studentid : studentids) {
                    List<String> stuQuestionIds = new ArrayList<>();//学生未收到或未得满分的试题ids
                    Double paperscore = 0.0;//试卷总分
                    for (QuestionVo question : questions) {
                        String questionid = question.getQuestionid();
                        boolean anyMatch = stuQuestions.stream().anyMatch(m -> m.get("studentid").equals(studentid)
                                && m.get("questionid").equals(questionid));
                        if (!anyMatch) {
                            stuQuestionIds.add(questionid);
                            paperscore = ArithUtil.add(paperscore, question.getScore());
                        }
                    }
                    Map stuQue = userMap.get(studentid);
                    stuQue.put("questionids", stuQuestionIds);
                    stuQue.put("paperscore", paperscore);
                    userMap.put(studentid, stuQue);
                }
            }

            for (Map.Entry<Integer, List<Map>> entry : classList.entrySet()) {
                Integer classid = entry.getKey();
                List<Map> groupList = entry.getValue();
                Map gMap = groupList.get(0);
                Map c = new HashMap();
                c.put("classid", classid);
                c.put("gradeid", gMap.get("gradeid"));
                c.put("classname", gMap.get("classname"));
                LinkedHashMap<Integer, List<Map>> groupCollect = groupList.stream().collect(Collectors.groupingBy(m -> (Integer) m.get("groupid")
                        , LinkedHashMap::new, Collectors.toList()));
                List<Map> groups2 = new ArrayList<>();
                for (Map.Entry<Integer, List<Map>> gentry : groupCollect.entrySet()) {
                    List<Map> studentList = gentry.getValue();
                    Map sMap = studentList.get(0);
                    Map g = new HashMap();
                    g.put("groupid", gentry.getKey());
                    g.put("groupname", sMap.get("groupname"));
                    g.put("groupnum", sMap.get("groupnum"));
                    g.put("grouptype", sMap.get("grouptype"));
                    List<Map> students = new ArrayList<>();
                    for (Map map : studentList) {
                        Map s = new HashMap();
                        Object studentid = map.get("studentid");
                        s.put("studentid", studentid);
                        Map stuMap = userMap.get(studentid);
                        s.put("studentname", stuMap.get("username"));
                        s.put("questionids", stuMap.get("questionids"));
                        s.put("paperscore", stuMap.get("paperscore"));
                        s.put("headpic", stuMap.get("headpic"));
                        students.add(s);
                    }

                    students = students.stream().sorted(Comparator.comparing(m -> m.get("studentname").toString()))
                                       .collect(Collectors.toList());
                    g.put("students", students);
                    groups2.add(g);
                }
                c.put("groups", groups2);
                classes.add(c);
            }
        }

        paper.put("classes", classes);
        return paper;
    }

    @Transactional(rollbackFor = Exception.class)
    public ResultVo savePaperClassStu(PaperGroupParam paperGroupParam) {
        try {
            //获取试卷详细信息
            TPaper paper = paperMapper.selectByPrimaryKey(paperGroupParam.getPaperid());

            if (paper == null) return new ResultVo(1, "发布失败");
            if (paper.getPaperstate() == 22) return new ResultVo(0, "保存成功");
            //班级
            List<PaperClassParam> classlst = paperGroupParam.getSelclass().stream().distinct().collect(Collectors.toList());
            List<Map> jtrclist = paperGroupParam.getJtrclist();

            if (N_Utils.isListEmpty(classlst) && N_Utils.isListEmpty(jtrclist)) {
                return new ResultVo(1, "发布作业未选择班级");
            } else {
                Integer stunum = 0;
                List pquestions;//试卷中所有试题
                Integer timestamp = N_Utils.getSecondTimestamp();
                Integer papertype = paper.getPapertype();
                Integer schoolid = paperGroupParam.getSchoolid();
                Integer paperid = paperGroupParam.getPaperid();

                Integer starttime = 0;
                Integer stoptime = 0;

                if(paperGroupParam.getTimetype() ==1){
                    //统一布置
                    starttime = paperGroupParam.getStarttime();
                    stoptime = paperGroupParam.getStoptime();
                    if(!N_Utils.isTrueInteger(starttime) || !N_Utils.isTrueInteger(stoptime)){
                        return new ResultVo(1, "发布作业未设置时间");
                    }
                }

                Integer showtype = paperGroupParam.getShowtype();
                Integer createid = paperGroupParam.getCreateid();
                Integer papernum = paper.getPapernum();
                Double paperscore = paper.getPaperscore();
                if (papertype == 2) {//附件
                    pquestions = paperScantronMapper.listPaperScansByPaperid(paperid);
                } else {
                    pquestions = paperQtypeQuestionMapper.listQuestionByPaperid(paperid);
                }
                //遍历班级，班级学生
                for (PaperClassParam c : classlst) {
                    Integer classid = c.getClassid();
                    Integer hasfc = c.getHasfc();
                    List<PaperStudentParam> students = c.getStudents();
                    if(paperGroupParam.getTimetype() == 2){
                        //分班布置
                        starttime = c.getStarttime();
                        stoptime = c.getStoptime();

                        if(!N_Utils.isTrueInteger(starttime) || !N_Utils.isTrueInteger(stoptime)){
                            return new ResultVo(1, "发布作业未设置时间");
                        }
                    }

                    //处理作业分组数据
                    if (papertype == 2) {//附件
                        stunum = setPaperGroup(stunum, pquestions, timestamp, schoolid, paperid
                                , starttime, stoptime, showtype, createid, papernum, paperscore, classid, students, hasfc);
                    } else {
                        stunum = setPaperGroup2(stunum, pquestions, timestamp, papertype, schoolid, paperid
                                , starttime, stoptime, showtype, createid, papernum, paperscore, classid, students, hasfc);
                    }
                }

                //集团校班级学生
                for (Map schoolmap : jtrclist) {
                    schoolid = Integer.parseInt(schoolmap.get("schoolid").toString());
                    List<Map> classlist = (List<Map>) schoolmap.get("classlist");
                    for (Map classmap : classlist) {
                        Integer classid = Integer.parseInt(classmap.get("classid").toString());
                        Integer hasfc = 0;
                        Object fc = classmap.get("hasfc");
                        if (N_Utils.isNotEmpty(fc)) {
                            hasfc = N_Utils.str2Int(fc.toString());
                        }
                        List<PaperStudentParam> students = JSON.parseArray(JSON.toJSONString(classmap.get("students")), PaperStudentParam.class);

                        if(paperGroupParam.getTimetype() == 2){
                            //分班布置
                            if(N_Utils.isEmpty(classmap.get("starttime")) || N_Utils.isEmpty(classmap.get("stoptime"))){
                                return new ResultVo(1, "发布作业未设置时间");
                            }
                            starttime = Integer.parseInt(classmap.get("starttime").toString());
                            stoptime = Integer.parseInt(classmap.get("stoptime").toString());
                        }

                        //处理作业分组数据
                        if (papertype == 2) {//附件
                            stunum = setPaperGroup(stunum, pquestions, timestamp, schoolid, paperid
                                    , starttime, stoptime, showtype, createid, papernum, paperscore, classid, students, hasfc);
                        } else {
                            stunum = setPaperGroup2(stunum, pquestions, timestamp, papertype, schoolid, paperid
                                    , starttime, stoptime, showtype, createid, papernum, paperscore, classid, students, hasfc);
                        }
                    }
                }

                if (stunum != 0) {
                    //保存作业分组、作业学生成功后，修改作业状态
                    Integer count = 0;
                    if (papertype == 1 || papertype == 3) {//题库作业、靶向作业
                        count = paperQtypeQuestionMapper.getQuestionCountCtype(paperGroupParam.getPaperid());
                    } else if (papertype == 2) {//附件作业
                        count = paperScantronMapper.getQuestionCountCtype(paperGroupParam.getPaperid());
                    }
                    Integer hashb = 0;
                    if (N_Utils.isListNotEmpty(jtrclist)) hashb = 1;

                    paperGroupParam.setHashb(hashb);
                    paperGroupParam.setPaperstate(22);

                    paperMapper.updatePaperState(paperGroupParam,count);
                    return new ResultVo(0, "发布成功", count);
                } else {
                    return new ResultVo(1, "当前学生都已掌握本次作业，请更换作业内容");
                }
            }
        } catch (Exception e) {
            log.error("发布作业失败：" + e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return new ResultVo(1, "发布失败");
        }
    }

    //处理作业分组数据
    private Integer setPaperGroup2(Integer stunum
            , List<TPaperQtypeQuestion> pquestions, Integer timestamp, Integer papertype, Integer schoolid
            , Integer paperid, Integer starttime, Integer stoptime, Integer showtype, Integer createid
            , Integer papernum, Double paperscore, Integer classid, List<PaperStudentParam> students,Integer hasfc) {
        List<TPaperStudentQuestion> savestuque=new ArrayList<>();
        if (N_Utils.isListNotEmpty(students)) {
            TPaperClass pg = new TPaperClass();
            pg.setPaperid(paperid);
            pg.setClassid(classid);
            pg.setPgstate(22);
            pg.setStarttime(starttime);
            pg.setStoptime(stoptime);
            pg.setShowtype(showtype);
            pg.setCreateid(createid);
            pg.setSchoolid(schoolid);
            pg.setCreatetime(timestamp);
            pg.setChecked(0);
            pg.setHasfc(hasfc);
            paperClassMapper.insertSelective(pg);

            //根据studentid集合去重
            List<PaperStudentParam> students2 = students.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(PaperStudentParam::getStudentid))), ArrayList::new));
            for (PaperStudentParam s : students2) {
                TPaperStudent ps = new TPaperStudent();
                ps.setPaperid(paperid);
                ps.setClassid(classid);
                ps.setStudentid(s.getStudentid());
                ps.setCreateid(createid);
                ps.setCreatetime(N_Utils.getSecondTimestamp());
                ps.setSchoolid(schoolid);
                if (papertype != 3) {//题库、附件作业
                    ps.setPapernum(papernum);
                    ps.setPaperscore(paperscore);
                    Integer psid = savePaperStu(ps);
                    for (TPaperQtypeQuestion q : pquestions) {
                        TPaperStudentQuestion sq=new TPaperStudentQuestion();
                        sq.setPaperid(paperid);
                        sq.setClassid(classid);
                        sq.setStudentid(s.getStudentid());
                        sq.setPsid(psid);
                        sq.setQuestionpid(q.getQuestionpid());
                        sq.setQuestionid(q.getQuestionid());
                        sq.setQscore(q.getPtqscore());
                        sq.setQn(q.getQn());
                        sq.setQorder(q.getPtqorder());
                        sq.setSchoolid(schoolid);
                        savestuque.add(sq);
                    }
                } else if (N_Utils.isListNotEmpty(s.getQuestions())) {//靶向作业
                    ps.setPapernum(s.getQuestions().size());
                    //获取学生的试卷分值信息
                    List<TPaperQtypeQuestion> stuques = pquestions.stream().filter(
                            (pq) -> s.getQuestions().stream().collect(Collectors.toList()).contains(pq.getQuestionpid())).collect(Collectors.toList());
                    if(N_Utils.isListEmpty(stuques)) continue;//学生收到的试题为空不保存
                    //计算学生试卷中试题总分值
                    double pscore = stuques.stream().collect(Collectors.summingDouble(TPaperQtypeQuestion::getPtqscore));
                    ps.setPaperscore(pscore);
                    ps.setQuestionids(JSON.toJSONString(s.getQuestions()));
                    Integer psid = savePaperStu(ps);
                    for (TPaperQtypeQuestion q : stuques) {
                        TPaperStudentQuestion sq=new TPaperStudentQuestion();
                        sq.setPaperid(paperid);
                        sq.setClassid(classid);
                        sq.setStudentid(s.getStudentid());
                        sq.setPsid(psid);
                        sq.setQuestionpid(q.getQuestionpid());
                        sq.setQuestionid(q.getQuestionid());
                        sq.setQscore(q.getPtqscore());
                        sq.setQn(q.getQn());
                        sq.setQorder(q.getPtqorder());
                        sq.setSchoolid(schoolid);
                        savestuque.add(sq);
                    }
                }
                stunum += 1;
            }
            if(N_Utils.isListNotEmpty(savestuque)) paperStudentQuestionMapper.batchSave(savestuque);
        }
        return stunum;
    }

    //报错作业学生并返回主键
    private Integer savePaperStu(TPaperStudent ps) {
        ps.setUserscore(0.0);
        ps.setPsstate(0);
        ps.setPschecked(0);
        ps.setAutocheck(0);
        ps.setCosttime(0);
        paperStudentMapper.insertUseGeneratedKeys(ps);
        return ps.getId();
    }

    //伙伴学校作业发布对象
    public List<Map> listGroupStudent(Integer paperid, Integer papertype, Integer groupid) {
        List<Map> students = paperClassMapper.listGroupStudent(groupid);//教师权限集团校分组
        List<Integer> studentids = students.stream().map(m -> (Integer) m.get("studentid")).distinct().collect(Collectors.toList());
        if (papertype == 3) {//靶向作业
            List<QuestionVo> questions = paperClassMapper.listPaperPQuestions(paperid);//获取作业母题列表
            List<String> questionids = questions.stream().map(QuestionVo::getQuestionid).collect(Collectors.toList());
            List<Map> stuQuestions = paperClassMapper.listStuQuestion(questionids, studentids);
            for (Map student : students) {
                Object studentid = student.get("studentid");
                List<String> stuQuestionIds = new ArrayList<>();//学生未收到或未得满分的试题ids
                Double paperscore = 0.0;//试卷总分
                for (QuestionVo question : questions) {
                    String questionid = question.getQuestionid();
                    boolean anyMatch = stuQuestions.stream().anyMatch(m -> m.get("studentid").equals(studentid)
                            && m.get("questionid").equals(questionid));
                    if (!anyMatch) {
                        stuQuestionIds.add(questionid);
                        paperscore = ArithUtil.add(paperscore, question.getScore());
                    }
                }
                student.put("questionids", stuQuestionIds);
                student.put("paperscore", paperscore);
            }
        }
        return students;
    }

    /**
     * @Description 获取可批阅人数
     * @Date 2023/11/17 9:52
     * @Author YWX
     * @Param [paperid, checkid]
     * @Return java.lang.Integer
     **/
    public Integer getCheckNum(Integer paperid, Integer checkid) {
        return paperStudentMapper.getCheckNum(paperid,checkid);
    }
}
