package com.xhkjedu.sstudy.service.paperstudent;

import com.alibaba.fastjson.JSON;
import com.xhkjedu.sstudy.mapper.gradeclass.ClassMapper;
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.PaperGroupMapper;
import com.xhkjedu.sstudy.mapper.paperstudent.PaperStudentMapper;
import com.xhkjedu.sstudy.model.paper.TPaper;
import com.xhkjedu.sstudy.model.paper.TPaperQtypeQuestion;
import com.xhkjedu.sstudy.model.paperstudent.TPaperGroup;
import com.xhkjedu.sstudy.model.paperstudent.TPaperStudent;
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.PaperGroupVo;
import com.xhkjedu.sstudy.vo.paperstudent.PaperStudentParam;
import com.xhkjedu.sstudy.vo.question.QuestionVo;
import com.xhkjedu.utils.N_Utils;
import com.xhkjedu.vo.ResultVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;
import java.util.stream.Collectors;

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

    @Autowired
    private PaperQtypeQuestionMapper paperQtypeQuestionMapper;
    @Autowired
    private PaperScantronMapper paperScantronMapper;

    /**
     *功能描述
     * @author WN
     * @date 2020/6/9
     * @param  * @param paperGroupVo
     * @return void
     */
    @Transactional(rollbackFor = Exception.class)
    public ResultVo savePaperGroup(PaperGroupParam paperGroupParam){
        ResultVo resultVo = null;
        try {
            //获取试卷详细信息
            TPaper paper = paperMapper.selectByPrimaryKey(paperGroupParam.getPaperid());
            if (paper.getPaperstate() == 22) return new ResultVo(0,"保存成功");
            //班级
            List<TPaperGroup> classlst = paperGroupParam.getClasslst().stream().distinct().collect(Collectors.toList());

            if(classlst.size()==0){
                return new ResultVo(1,"发布作业未选择班级");
            }else{

                //保存作业分组、作业学生
                resultVo = this.savePaperStudent(paperGroupParam,classlst,paper);
                if(resultVo.getCode()==1){
                    return resultVo;
                }else{
                    //获取作业是否全是非主观题
                    int count = 0;
                    if(paper.getPapertype()==1){
                        //题库作业
                        count = paperQtypeQuestionMapper.getQuestionCountCtype(paperGroupParam.getPaperid());
                    }else{
                        //答题卡作业
                        count = paperScantronMapper.getQuestionCountCtype(paperGroupParam.getPaperid());
                    }

                    //保存作业分组、作业学生成功后，修改作业状态
                    paperMapper.updatePaperState(22,paperGroupParam.getPaperid(),count);

                    resultVo.setObj(count);//如果count=0则，代表全部是选择题
                }
            }

        }catch (Exception e){
            log.error("发布作业失败：" + e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return new ResultVo(1,"发布失败");
        }
        return resultVo;
    }

    private ResultVo savePaperStudent(PaperGroupParam paperGroupParam, List<TPaperGroup> classlst, TPaper paper){
        List<TPaperGroup> savegroup = new ArrayList<>();//班级分组
        List<TPaperStudent> saveps = new ArrayList<>();//班级分组学生

        for (TPaperGroup pg:classlst){
            List<Integer> groups = pg.getGroups();
            if(groups==null || groups.size()==0){
                return new ResultVo(1,"发布作业未选择分组");
            }else{
                pg.setPaperid(paperGroupParam.getPaperid());
                pg.setPgstate(22);//布置作业
                pg.setStarttime(paperGroupParam.getStarttime());
                pg.setStoptime(paperGroupParam.getStoptime());
                pg.setShowtype(paperGroupParam.getShowtype());
                pg.setCreateid(paperGroupParam.getCreateid());
                pg.setSchoolid(paperGroupParam.getSchoolid());
                pg.setCreatetime(N_Utils.getSecondTimestamp());
                pg.setChecked(0);


                savegroup.add(pg);
                String groupids = StringUtils.join(groups,",");
                //获取选中班级分组下所有学生
                List<Integer> stus = classMapper.listStudentidsByGroupids(groupids);

                for(Integer stu:stus){
                    TPaperStudent ps = new TPaperStudent();
                    ps.setPaperid(paperGroupParam.getPaperid());
                    ps.setClassid(pg.getClassid());
                    ps.setStudentid(stu);
                    ps.setPapernum(paper.getPapernum());
                    ps.setPaperscore(paper.getPaperscore());
                    ps.setCreateid(paperGroupParam.getCreateid());
                    ps.setSchoolid(paperGroupParam.getSchoolid());
                    ps.setCreatetime(N_Utils.getSecondTimestamp());

                    saveps.add(ps);
                }
            }
        }

        //批量保存作业班级，作业班级学生信息
        try {
            paperGroupMapper.insertList(savegroup);
        } catch (Exception e) {
            if (e instanceof DuplicateKeyException) {
                return new ResultVo(0,"保存成功");
            }
        }
        paperStudentMapper.saveBatchPaperStudent(saveps);
        return new ResultVo(0,"保存成功");
    }

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

    /**
     * 获取发布对象
     *
     * @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) {
        Map paper = new HashMap();
        List<Map> groups = paperGroupMapper.listGroupByTeacherId(createid);//教师权限分组
        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> users = paperGroupMapper.listUserByIds(studentids);
        Map<Integer, Map> userMap = users.stream().collect(Collectors.toMap(m -> (Integer) m.get("userid"), m -> m));
        if (papertype == 3) {//靶向作业
            List<QuestionVo> questions = paperGroupMapper.listPaperQuestions(paperid);
            paper.put("questions", questions);
            List<String> questionids = questions.stream().map(QuestionVo::getQuestionid).collect(Collectors.toList());
            List<Map> stuQuestions = paperGroupMapper.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);
            }
        }
        List<Map> classes = new ArrayList<>();
        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());

            if (classlst == null || classlst.size() == 0) {
                return new ResultVo(1, "发布作业未选择班级");
            } else {
                List<TPaperGroup> savegroup = new ArrayList<>();//班级分组
                List<TPaperStudent> savestu = new ArrayList<>();//班级分组学生
                List<TPaperQtypeQuestion> pquestions = new ArrayList<>();//试卷中所有试题
                Integer timestamp = N_Utils.getSecondTimestamp();
                Integer papertype = paper.getPapertype();
                if (papertype == 3) {
                    pquestions = paperQtypeQuestionMapper.listQuestionByPaperid(paper.getPaperid());
                }
                //遍历班级，班级学生
                for (PaperClassParam c : classlst) {
                    List<PaperStudentParam> students = c.getStudents();
                    if (students == null || students.size() == 0) {
                        return new ResultVo(1, "发布作业未选择学生");
                    } else {
                        TPaperGroup pg = new TPaperGroup();
                        pg.setPaperid(paper.getPaperid());
                        pg.setClassid(c.getClassid());
                        pg.setPgstate(22);
                        pg.setStarttime(paperGroupParam.getStarttime());
                        pg.setStoptime(paperGroupParam.getStoptime());
                        pg.setShowtype(paperGroupParam.getShowtype());
                        pg.setCreateid(paperGroupParam.getCreateid());
                        pg.setCreatetime(timestamp);
                        pg.setSchoolid(paper.getSchoolid());
                        pg.setChecked(0);

                        //根据studentid集合去重
                        List<PaperStudentParam> students2 = students.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(PaperStudentParam::getStudentid))), ArrayList::new));
                        boolean rtn = false;
                        for (PaperStudentParam s : students2) {
                            TPaperStudent ps = new TPaperStudent();
                            ps.setPaperid(paper.getPaperid());
                            ps.setClassid(pg.getClassid());
                            ps.setStudentid(s.getStudentid());
                            ps.setCreateid(paperGroupParam.getCreateid());
                            ps.setCreatetime(N_Utils.getSecondTimestamp());
                            ps.setSchoolid(paper.getSchoolid());
                            if (papertype != 3) {//题库、附件作业
                                ps.setPapernum(paper.getPapernum());
                                ps.setPaperscore(paper.getPaperscore());
                                savestu.add(ps);
                                rtn = true;
                            } 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.getQuestionid())).collect(Collectors.toList());
                                //计算学生试卷中试题总分值
                                double pscore = stuques.stream().collect(Collectors.summingDouble(TPaperQtypeQuestion::getPtqscore));
                                ps.setPaperscore(pscore);
                                ps.setQuestionids(JSON.toJSONString(s.getQuestions()));
                                savestu.add(ps);
                                rtn = true;
                            }
                        }
                        if (rtn) {//班级有学生的才保存作业分组信息
                            savegroup.add(pg);
                        }
                    }
                }

                if (savestu != null && savestu.size() > 0) {
                    paperGroupMapper.insertList(savegroup);//保存作业班级信息
                    paperStudentMapper.saveBatchPaperStudent(savestu);//保存班级学生信息
                    //保存作业分组、作业学生成功后，修改作业状态
                    Integer count = 0;
                    if (papertype == 1) {//题库作业
                        count = paperQtypeQuestionMapper.getQuestionCountCtype(paperGroupParam.getPaperid());
                    } else if (papertype == 2) {//附件作业
                        count = paperScantronMapper.getQuestionCountCtype(paperGroupParam.getPaperid());
                    } else {//靶向作业
                        count = pquestions.stream().filter(q -> q.getCtype().equals(3)).collect(Collectors.toList()).size();
                    }
                    paperMapper.updatePaperState(22, paperGroupParam.getPaperid(), 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, "发布失败");
        }
    }
}
