package com.xhkjedu.sexam.service.exam;

import com.xhkjedu.sexam.mapper.exam.EBaseMacMapper;
import com.xhkjedu.sexam.mapper.exam.EBaseMapper;
import com.xhkjedu.sexam.mapper.exam.EClassMapper;
import com.xhkjedu.sexam.mapper.exam.EClassStudentMapper;
import com.xhkjedu.sexam.mapper.exam.ESubjectMapper;
import com.xhkjedu.sexam.mapper.paper.EPaperMapper;
import com.xhkjedu.sexam.mapper.paper.EPaperQtypeMapper;
import com.xhkjedu.sexam.mapper.paperstudent.EPaperStudentMapper;
import com.xhkjedu.sexam.mapper.paperstudent.EPaperStudentQuestionMapper;
import com.xhkjedu.sexam.mapper.system.UserMapper;
import com.xhkjedu.sexam.model.exam.EBase;
import com.xhkjedu.sexam.model.exam.EBaseMac;
import com.xhkjedu.sexam.model.exam.EClass;
import com.xhkjedu.sexam.model.exam.EClassStudent;
import com.xhkjedu.sexam.model.exam.ESubject;
import com.xhkjedu.sexam.model.paper.EPaper;
import com.xhkjedu.sexam.model.paper.EPaperQtypeQuestion;
import com.xhkjedu.sexam.model.paperstudent.EPaperStudent;
import com.xhkjedu.sexam.model.paperstudent.EPaperStudentQuestion;
import com.xhkjedu.sexam.vo.exam.EBaseVo;
import com.xhkjedu.sexam.vo.system.UserVo;
import com.xhkjedu.utils.N_Utils;
import com.xhkjedu.vo.ResultVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class EBaseService {
    @Resource
    private EBaseMapper eBaseMapper;
    @Resource
    private EClassMapper eClassMapper;
    @Resource
    private EClassStudentMapper eClassStudentMapper;
    @Resource
    private ESubjectMapper eSubjectMapper;
    @Resource
    private EPaperMapper ePaperMapper;
    @Resource
    private UserMapper userMapper;
    @Resource
    private EPaperStudentMapper ePaperStudentMapper;
    @Resource
    private EBaseMacMapper eBaseMacMapper;
    @Resource
    private EPaperQtypeMapper ePaperQtypeMapper;
    @Resource
    private EPaperStudentQuestionMapper ePaperStudentQuestionMapper;

    /**
     * 发起考试
     *
     * @return com.xhkjedu.vo.ResultVo
     * @Param [model]
     * @Author ywx
     * @Date 2022/7/18 10:37
     **/
    @Transactional(rollbackFor = Exception.class)
    public ResultVo save(EBase model) {
        try {
            //考试
            model.setExamstate(0);
            model.setDeleted(1);
            model.setCreatetime(N_Utils.getSecondTimestamp());
            eBaseMapper.insertUseGeneratedKeys(model);
            Integer examid = model.getId();

            ResultVo vo = saveExam(model, examid);//保存考试基本信息
            if (vo != null) return vo;

            return new ResultVo(0, "保存成功", examid);
        } catch (Exception e) {
            log.error("发起考试失败", e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return new ResultVo(1, "保存失败");
        }
    }

    //保存考试基本信息
    private ResultVo saveExam(EBase model, Integer examid) {
        List<Integer> classids = model.getClassids();
        List<EClassStudent> students = eClassStudentMapper.listByClassIds(classids);
        int stuNum = students.stream().distinct().collect(Collectors.toList()).size();
        if (stuNum < students.size()) return new ResultVo(1, "有重复学生");

        //考试班级
        List<EClass> classes = eClassMapper.listByClassIds(classids);
        classes.forEach(c -> c.setExamid(examid));
        eClassMapper.insertList(classes);

        //考试学生
        students.forEach(s -> s.setExamid(examid));
        eClassStudentMapper.insertList(students);

        //考试科目
        List<ESubject> subjects = model.getSubjects();//考试科目
        List<EPaper> papers = new ArrayList<>();//考试试卷
        for (ESubject s : subjects) {
            s.setExamid(examid);
            s.setEsstate(0);
            EPaper p = new EPaper();
            p.setExamid(examid);
            p.setSubjectid(s.getSubjectid());
            p.setPtype(0);
            p.setPnum(0);
            p.setPscore(0.0);
            p.setAnswered(0);
            p.setCorrecttype(0);
            papers.add(p);
        }
        eSubjectMapper.insertList(subjects);//考试科目

        Integer createid = model.getCreateid();
        Integer createtime = model.getCreatetime();
        for (int i = 0; i < papers.size(); i++) {
            EPaper ePaper = papers.get(i);
            ePaper.setEsid(subjects.get(i).getId());
            ePaper.setCreateid(createid);
            ePaper.setCreatetime(createtime);
        }
        ePaperMapper.insertList(papers);//考试试卷

        return null;
    }

    //删除
    public Integer deleteById(Integer id) {
        return eBaseMapper.deleteById(id);
    }

    //修改
    @Transactional(rollbackFor = Exception.class)
    public ResultVo update(EBase model) {
        try {
            EBaseVo exam = eBaseMapper.getExamStateById(model.getExamid());
            int timestamp = N_Utils.getSecondTimestamp() - 30 * 60;
            if (exam.getBegintime().compareTo(timestamp) != -1) return new ResultVo(1, "开考前30分钟禁止编辑");
            eBaseMapper.updateByPrimaryKeySelective(model);
            Integer examid = model.getExamid();
            eBaseMapper.deleteClassAndSubjectById(examid);//删除关联的班级和科目
            ResultVo vo = saveExam(model, examid);//保存考试基本信息
            if (vo != null) return vo;
            return new ResultVo(0, "修改成功");
        } catch (Exception e) {
            log.error("修改考试失败", e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return new ResultVo(1, "修改失败");
        }
    }

    //获取详情
    public Map findById(Integer id) {
        Map map = eBaseMapper.findById2(id);//考试基本信息(带考试人数)
        List<Map> subjects = eSubjectMapper.listSubjectSet(id);//考试科目设置列表
        map.put("subjects", subjects);
        List<Map> classes = eClassMapper.listByExamId(id);
        map.put("classes", classes);
        return map;
    }

    //获取列表
    public List<Map> listAll(EBase base) {
        return eBaseMapper.listAll(base);
    }

    //考试设置
    public void setExam(List<ESubject> subjects) {
        eSubjectMapper.setExam(subjects);
    }

    //发布考试
    @Transactional(rollbackFor = Exception.class)
    public void updateExamStateStart(Integer examid, String examcomm, List<UserVo> students,Integer exammode) {
        //更改考试状态
        eBaseMapper.postExam(examid, examcomm);
        //发布考试，获取考试试卷题量和分值
        List<EPaper> papers = ePaperMapper.listNumAndScoreByExamId(examid);
        List<EPaperStudent> studentList = new ArrayList<>();
        int timestamp = N_Utils.getSecondTimestamp();
        for (EPaper paper : papers) {
            Integer esid = paper.getEsid();
            Integer epid = paper.getEpid();
            Integer pnum = paper.getPnum();
            Double pscore = paper.getPscore();
            String subjectid = paper.getSubjectid();
            for (UserVo student : students) {
                EPaperStudent es = new EPaperStudent();
                es.setExamid(examid);
                es.setEsid(esid);
                es.setEpid(epid);
                es.setSubjectid(subjectid);
                es.setClassid(student.getClassid());
                es.setStudentid(student.getUserid());
                es.setSstate(0);
                es.setChecked(0);
                es.setNum(pnum);
                es.setScore(pscore);
                es.setStuscore(0.0);
                es.setCosttime(0);
                es.setCreatetime(timestamp);
                es.setHasbad(0);
                studentList.add(es);
            }
        }
        ePaperStudentMapper.insertList(studentList);//保存考试学生信息

        if(exammode == 2){
            //代表线下考试，生成学生和试题的关联关系
            List<EPaperStudentQuestion> stuqlist = new ArrayList<>();
            for (EPaper paper : papers) {
                Integer epid = paper.getEpid();
                //获取试卷中所有试题
                List<EPaperQtypeQuestion> queslist = ePaperQtypeMapper.listQuestionsByEpid(epid);
                for (EPaperStudent ps : studentList) {
                    for(EPaperQtypeQuestion q : queslist){
                        EPaperStudentQuestion epsq = new EPaperStudentQuestion();
                        epsq.setClassid(ps.getClassid());
                        epsq.setStudentid(ps.getStudentid());
                        epsq.setEpid(ps.getEpid());
                        epsq.setEpsid(ps.getId());
                        epsq.setEptqid(q.getEptqid());
                        epsq.setCtype(q.getCtype());
                        epsq.setQuestionid(q.getQuestionid());
                        epsq.setQn(q.getQn());
                        epsq.setQorder(q.getQorder());
                        epsq.setAnswered(0);
                        epsq.setAnswertype(0);
                        epsq.setConverted(0);
                        epsq.setCosttime(0);
                        epsq.setQscore(q.getScore());
                        epsq.setStuscore(0.0);
                        epsq.setChecked(0);
                        epsq.setGood(0);
                        epsq.setBad(0);
                        stuqlist.add(epsq);
                    }
                }
            }
            ePaperStudentQuestionMapper.insertList(stuqlist);
        }
    }

    //结束考试
    public void updateExamStateEnd(Integer examid) {
        eBaseMapper.updateExamState(examid, 2);

    }

    //获取考试班级
    public List<Map> listClass(Integer examid) {
        List<Map> classes = eClassMapper.listByExamId(examid);
        return classes;
    }

    //获取考试和班级信息
    public Map getExamAndClass(Integer examid) {
        Map map = eBaseMapper.findById2(examid);
        List<Map> classes = eClassMapper.listByExamId(examid);
        map.put("classes", classes);
        return map;
    }

    //考试学生
    public List<Map> listStu(EClassStudent cs) {
        List<Map> students = eClassStudentMapper.listByExamId(cs);
        Integer examid = cs.getExamid();
        List<Map> classes = eClassMapper.listByExamId(examid);
        Map<Object, Object> classMap = classes.stream().collect(Collectors.toMap(m -> m.get("classid"), m -> m.get("classname")));
        students.forEach(s -> s.put("classname", classMap.get(s.get("classid"))));
        return students;
    }

    //移除考试学生
    @Transactional(rollbackFor = Exception.class)
    public ResultVo delStu(Integer ecsid) {
        EClassStudent student = eClassStudentMapper.selectByPrimaryKey(ecsid);
        eClassStudentMapper.deleteByPrimaryKey(ecsid);
        EBaseVo exam = eBaseMapper.getExamStateById(student.getExamid());
        int timestamp = N_Utils.getSecondTimestamp() - 30 * 60;
        if (exam.getBegintime().compareTo(timestamp) != -1) return new ResultVo(1, "开考前30分钟禁止移除学生");
        eClassMapper.updateClassNumByCsId(student.getExamid(), student.getClassid());
        return new ResultVo(0, "移除考试学生成功");
    }

    //考试科目列表
    public Map listSubject(Integer examid) {
        Map map = eBaseMapper.findById(examid);
        List<Map> subjects = eSubjectMapper.listSubject(examid);
        map.put("subjects", subjects);
        return map;
    }

    //根据考试id获取名称
    public String getNameByExamId(Integer examid) {
        return eBaseMapper.getNameByExamId(examid);
    }

    //获取考生
    public List<UserVo> listStuByExamId(Integer examid) {
        return userMapper.listStuByExamId(examid);
    }

    //根据考试id获取考试状态
    public EBaseVo getExamStateById(Integer examid) {
        return eBaseMapper.getExamStateById(examid);
    }

    //获取未完成的考试试卷数量
    public Integer countNoCompletePaper(Integer examid) {
        return eSubjectMapper.countNoCompletePaper(examid);
    }

    public List<UserVo> listTeacherByClassIds(String classids) {
        return userMapper.listTeacherByClassIds(classids);
    }

    //设置出卷人
    public void setSubjectTeacher(ESubject subject) {
        eSubjectMapper.updateByPrimaryKeySelective(subject);
    }

    //考试设置状态
    public Map getSetState(Integer examid) {
        return eBaseMapper.getSetState(examid);
    }

    //保存发布信息
    public void savePostExam(Integer examid, String examcomm) {
        EBase b = new EBase();
        b.setExamid(examid);
        b.setExamcomm(examcomm);
        eBaseMapper.updateByPrimaryKeySelective(b);
    }

    //获取mac编号
    public String getMacNumber(String mac) {
        String macCode = "PC-";
        Integer ebmid = eBaseMacMapper.getIdByMac(mac);//根据mac获取主键
        if (ebmid == null) {
            EBaseMac bm = new EBaseMac();
            bm.setMac(mac);
            eBaseMacMapper.insertUseGeneratedKeys(bm);
            ebmid = bm.getId();
        }
        return macCode + ebmid;
    }
}
