package com.xhkjedu.sexam.service.paperstudent;

import com.alibaba.fastjson.JSON;
import com.xhkjedu.sexam.mapper.paper.EPaperFileMapper;
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.paperstudent.EScanbatchMapper;
import com.xhkjedu.sexam.mapper.paperstudent.EScanerrorMapper;
import com.xhkjedu.sexam.mapper.system.UserMapper;
import com.xhkjedu.sexam.model.paper.EPaperQtype;
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.model.paperstudent.EScanerror;
import com.xhkjedu.sexam.utils.ConvertUtil;
import com.xhkjedu.sexam.utils.ExamUtil;
import com.xhkjedu.sexam.vo.paperstudent.EPaperStudentVo;
import com.xhkjedu.sexam.vo.paperstudent.PaperStudentWebVo;
import com.xhkjedu.sexam.vo.paperstudent.PsqAnswerVo;
import com.xhkjedu.utils.N_Utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * @Description 学生试卷信息
 * @Author WN
 * Date 2022/7/26 14:00
 **/
@Service
@Slf4j
public class EPaperStudentService {
    @Resource
    private EPaperStudentMapper ePaperStudentMapper;
    @Resource
    private EPaperQtypeMapper ePaperQtypeMapper;
    @Resource
    private EPaperStudentQuestionMapper ePaperStudentQuestionMapper;
    @Resource
    private UserMapper userMapper;
    @Resource
    private EPaperFileMapper ePaperFileMapper;
    @Resource
    private EScanbatchMapper eScanbatchMapper;
    @Resource
    private EScanerrorMapper eScanerrorMapper;
    @Autowired
    private ConvertUtil convertUtil;

    /**
     * @Description 学生进行中考试列表
     * @Param [eps]
     * @Return java.util.List<java.util.Map>
     * @Author wn
     * @Date 2022/7/27 10:35
     **/
    public List<Map> listExamPapersForStudent(EPaperStudent eps) {
        return ePaperStudentMapper.listExamPapersForStudent(eps.getStudentid());
    }

    public Map getExamSubjectPaperByEpsid(Integer epsid){
        Map map = ePaperStudentMapper.getExamSubjectPaperByEpsid(epsid);
        Long times = null;
        if(map.get("sdate")!=null && map.get("begintime")!=null && map.get("endtime")!=null){
            long bg = ExamUtil.strToTimestamp(map.get("sdate").toString() + " " + map.get("begintime").toString() + ":00");
            long ed = ExamUtil.strToTimestamp(map.get("sdate").toString() + " " + map.get("endtime").toString() + ":00");
            times = ExamUtil.subtract(ed,bg);
        }
        map.put("times",times);
        return map;
    }

    /**
     * 学生已结束考试列表
     *
     * @Description
     * @Param [eps]
     * @Return java.util.List<java.util.Map>
     * @Author wn
     * @Date 2022/7/27 11:34
     **/
    public List<Map> listExamsEndForStudent(EPaperStudent eps) {
        return ePaperStudentMapper.listExamsEndForStudent(eps.getStudentid());
    }

    /**
     * @Description 开始考试(andorid)
     * @Param [eps]
     * @Return java.util.Map
     * @Author wn
     * @Date 2022/7/27 11:48
     **/
    public List<Map> startPaperForAndroid(EPaperStudent eps) {
        Integer epsid = eps.getEpsid();
        //获取试卷基本信息
        EPaperStudentVo psvo = ePaperStudentMapper.getExamSubjectByEpsid(epsid);
        Integer ptype = psvo.getPtype();

        List<Map> questions = null;
        if (ptype == 1) {
            //题库试卷试题
            questions = ePaperStudentMapper.listStuPaperQuestionsForAndroid(epsid);
        } else {
            questions = ePaperStudentMapper.listStuPaperFjQuestionsForAndroid(epsid);
        }
        //判断是否生成学生试卷，未生成则需要生成，如果已生成直接返回
        if (questions == null || questions.size() == 0) {

            //保存试卷关联信息
            savePaperStudentQuestion(psvo);
            //保存后重新获取返回
            if (ptype == 1) {
                questions = ePaperStudentMapper.listStuPaperQuestionsForAndroid(epsid);
            } else {
                questions = ePaperStudentMapper.listStuPaperFjQuestionsForAndroid(epsid);
            }
        }

        return questions;
    }

    //保存学生试卷关联信息
    private void savePaperStudentQuestion(EPaperStudentVo psvo) {
        //生成学生试卷
        List<EPaperQtypeQuestion> pqlist = ePaperQtypeMapper.listQuestionsByEpid(psvo.getEpid());

        List<EPaperStudentQuestion> psqlist = new ArrayList<>();
        for (EPaperQtypeQuestion q : pqlist) {
            EPaperStudentQuestion sq = new EPaperStudentQuestion();
            sq.setClassid(psvo.getClassid());
            sq.setStudentid(psvo.getStudentid());
            sq.setEpid(psvo.getEpid());
            sq.setEpsid(psvo.getEpsid());
            sq.setEptqid(q.getEptqid());
            sq.setCtype(q.getCtype());
            sq.setQuestionid(q.getQuestionid());
            sq.setQn(q.getQn());
            sq.setQorder(q.getQorder());
            sq.setQscore(q.getScore());
            sq.setAnswered(0);
            sq.setConverted(0);
            sq.setChecked(0);
            sq.setStuscore(0.0);
            sq.setCosttime(0);
            sq.setGood(0);
            sq.setBad(0);
            psqlist.add(sq);
        }
        ePaperStudentQuestionMapper.insertList(psqlist);//保存试卷
    }

    /**
     * @Description 开始考试（web）
     * @Param [eps]
     * @Return java.util.List<java.util.Map>
     * @Author wn
     * @Date 2022/7/27 15:36
     **/
    public EPaperStudentVo startPaperForWeb(EPaperStudent eps) {
        Integer epsid = eps.getEpsid();
        //获取试卷基本信息
        EPaperStudentVo psvo = ePaperStudentMapper.getExamSubjectByEpsid(epsid);
        Integer ptype = psvo.getPtype();

        List<EPaperQtype> questions = null;
        if (ptype == 1) {
            //题库试卷试题
            questions = ePaperStudentMapper.listStuPaperQuestionsForWeb(epsid);
        } else {
            questions = ePaperStudentMapper.listStuPaperFjQuestionsForWeb(epsid);
        }
        //判断是否生成学生试卷，未生成则需要生成，如果已生成直接返回
        if (questions == null || questions.size() == 0) {
            //保存试卷关联信息
            savePaperStudentQuestion(psvo);
            //保存后重新获取返回
            if (ptype == 1) {
                questions = ePaperStudentMapper.listStuPaperQuestionsForWeb(epsid);
            } else {
                questions = ePaperStudentMapper.listStuPaperFjQuestionsForWeb(epsid);
            }
        }

        if(ptype==2){
            List<Map> files = ePaperFileMapper.listPaperFiles(psvo.getEpid());
            psvo.setFiles(files);
        }

        psvo.setQtypelist(questions);
        return psvo;
    }

    /**
     * @Description 提交单题
     * @Param [psq]
     * @Return void
     * @Author wn
     * @Date 2022/7/28 13:47
     **/
    public void saveCommitQuestion(EPaperStudentQuestion psq) throws Exception {
        try {
            //学生作答提交时先判断试卷是否设置的正确答案
            PsqAnswerVo answerVo = ePaperStudentQuestionMapper.getPaperQuestionAnswer(psq.getEpsqid());
            setCommitQuestion(psq,answerVo);
            ePaperStudentQuestionMapper.updateStuAnswer(psq);
        }catch (Exception e){
            log.error("提交试题失败："+e.getMessage());
            throw new Exception("提交试题失败");
        }

    }

    //判断单道题情况
    private void setCommitQuestion(EPaperStudentQuestion psq,PsqAnswerVo answerVo){
        int timestamp = N_Utils.getSecondTimestamp();
        psq.setAnswertime(timestamp);
        int coverted = 1;//是否转换0未转换1已转换2转换失败
        String stuanswer = psq.getStuanswer();
        List<String> stuanswers = JSON.parseArray(stuanswer, String.class);
        Double stuscore = 0D;

        if(N_Utils.isListEmpty(stuanswers) && N_Utils.isEmpty(psq.getStuanswertxt())
                && N_Utils.isEmpty(psq.getStuanswertxt())){
            psq.setStuscore(stuscore);
            psq.setChecked(2);
            psq.setChecktime(timestamp);
            psq.setAnswered(0);
        }else{
            //试卷已经设置了正确答案
            if (answerVo.getAnswered() == 1){
                String qanswer = answerVo.getAnswer();
                List<String> qanswers = JSON.parseArray(qanswer,String.class);
                int ctype = answerVo.getCtype();
                if(psq.getAnswertype() == 1){
                    if(N_Utils.isObjectiveQuestion(ctype)){
                        //客观题进行批阅
                        if(ctype == 1 || ctype == 4 || ctype == 5 || ctype == 6){
                            //单选、判断
                            if(stuanswer.equalsIgnoreCase(qanswer)) {
                                stuscore = answerVo.getScore();
                            }
                        }else if(ctype == 2){//多选
                            //多选、选错不得分
                            if(stuanswers.get(0).length() <= qanswer.length()){
                                String[] qanswerList = qanswers.get(0).split("");
                                String[] stuanswerList = stuanswers.get(0).split("");
                                int rightNum = 0;//选对个数
                                for(String sa : stuanswerList){
                                    int right = 0;
                                    for(String qa : qanswerList){
                                        if(qa.equals(sa)){
                                            right = 1;
                                            rightNum ++;
                                        }
                                    }
                                    if(right == 0){//说明选错
                                        rightNum = 0;
                                        break;
                                    }
                                }
                                if(rightNum>0){
                                    if(qanswerList.length == rightNum){
                                        //全选对
                                        stuscore = answerVo.getScore();
                                    }else if (qanswerList.length > rightNum){
                                        //少选得半分
                                        stuscore = ExamUtil.div(answerVo.getScore(),2,1);
                                    }
                                }
                            }
                        }else if(ctype == 7 || ctype == 8 || ctype == 10){
                            //完形填空、阅读理解、任务型阅读
                            Double qscore = ExamUtil.div(answerVo.getScore(),qanswers.size());
                            Double stuScoreDouble = 0d;
                            for(int i=0;i<qanswers.size();i++){
                                if(qanswers.get(i).equalsIgnoreCase(stuanswers.get(i))){
                                    stuScoreDouble = ExamUtil.add(stuScoreDouble,qscore);
                                }
                            }
                            stuscore = ExamUtil.round(stuScoreDouble,1);
                        }
                        if(stuscore.compareTo(answerVo.getScore()) == 1){
                            stuscore = answerVo.getScore();
                        }

                        psq.setChecked(2);
                        psq.setChecktime(timestamp);
                    }else{
                        if(stuanswers.size() > 1){
                            coverted = 0;//上传的多张图片设为0未转换
                        }
                        psq.setChecked(0);
                    }
                }else{
                    psq.setChecked(0);
                }
            }else{
                psq.setStuscore(stuscore);
                psq.setChecked(0);
            }
        }
        psq.setStuscore(stuscore);
        Integer costtime = answerVo.getCosttime();
        if(costtime == null){
            costtime = 0;
        }
        if(psq.getCosttime() == null){
            psq.setCosttime(costtime);
        }else{
            psq.setCosttime(psq.getCosttime());
        }

        psq.setConverted(coverted);
    }

    /**
     * @Description 提交试卷
     * @Param [epsid]
     * @Return int
     * @Author wn
     * @Date 2022/7/28 16:59
     **/
    @Transactional(rollbackFor = Exception.class)
    public void saveCommitPaper(Integer epsid){
        EPaperStudent ps = ePaperStudentMapper.selectByPrimaryKey(epsid);
        if(ps == null || ps.getSstate() == 2){
            return;
        }
        EPaperStudent paperStudent = new EPaperStudent();
        paperStudent.setEpsid(epsid);
        paperStudent.setSstate(2);
        paperStudent.setEndtime(N_Utils.getSecondTimestamp());

        //更改试卷中学生未提交的试题设置为0分，标记为已批改
        ePaperStudentQuestionMapper.updateStuQuesitonNoCommit(epsid);
        //获取试卷中未批阅试题数量
        int noCheckNum = ePaperStudentQuestionMapper.getStuQuestionNoCheckNum(epsid);
        int checked = 0;
        if(noCheckNum == 0){
            checked = 2;//试卷中所有试题都批完后标识试卷已批改
        }
        paperStudent.setChecked(checked);
        ePaperStudentMapper.updateStudentPaper(paperStudent);//修改试卷信息
        chandleStudentQuestionNoconvertedPic(epsid,1);//处理试卷中多张图片未合并情况
    }

    //处理试卷中未已提交需要合并的图片,type1代表线上2代表扫码答题卡图片
    private void chandleStudentQuestionNoconvertedPic(Integer epsid,Integer type){
        List<EPaperStudentQuestion> psqlist = ePaperStudentQuestionMapper.listStuQuesitonStuAnswerPic(epsid);
        if(N_Utils.isListNotEmpty(psqlist)){
            for(EPaperStudentQuestion sq : psqlist){
                List<String> stuanswer = JSON.parseArray(sq.getStuanswer(),String.class);
                if(N_Utils.isListNotEmpty(stuanswer) && stuanswer.size()>1){
                    convertUtil.imgMerge(sq.getEpsqid(),stuanswer,type);
                }
            }
        }
    }

    /**
     * @Description 提交试卷、试题（网页端）
     * @Param [pswvo]
     * @Return void
     * @Author wn
     * @Date 2022/7/28 19:18
     **/
    public void saveCommitPaperForWeb(PaperStudentWebVo pswvo){
        List<EPaperStudentQuestion> sqlist = pswvo.getQuestions();//学生提交试卷中试题
        EPaperStudent ps = ePaperStudentMapper.selectByPrimaryKey(pswvo.getEpsid());
        //试卷不存在或者已提交
        if(ps == null || ps.getSstate() == 2){
            return;
        }
        //获取试卷中所有试题答案及分值
        List<PsqAnswerVo> anvolist = ePaperStudentQuestionMapper.listPaperQuestionsAnswer(pswvo.getEpsid());
        Integer checknum = 0;//记录试卷中试题批阅数量
        Double paperscore = 0D;//学生试卷得分
        for(EPaperStudentQuestion q : sqlist){

            //获取该试题正确答案
            PsqAnswerVo anvo = anvolist.stream().filter(a -> a.getEpsqid().equals(q.getEpsqid())).findFirst().orElse(null);

            setCommitQuestion(q,anvo);
            if(q.getChecked() == 2){
                checknum ++;
            }
            paperscore = ExamUtil.add(paperscore, q.getStuscore());
        }
        EPaperStudent paperStudent = new EPaperStudent();
        paperStudent.setEpsid(pswvo.getEpsid());
        paperStudent.setEndtime(N_Utils.getSecondTimestamp());
        paperStudent.setSstate(2);
        paperStudent.setStuscore(paperscore);
        int checked = 0;
        if(checknum == sqlist.size()){
            checked = 2;
        }
        paperStudent.setChecked(checked);

        ePaperStudentQuestionMapper.updateBatchStuQuestion(sqlist);
        ePaperStudentMapper.updateStudentPaper(paperStudent);

        //获取试卷中需要合并图片的试题
        chandleStudentQuestionNoconvertedPic(pswvo.getEpsid(),1);
    }

    /**
     * @Description 答题卡扫描时保存
     * @Param [pswvo]
     * @Return void
     * @Author wn
     * @Date 2022/8/3 9:17
     **/
    @Transactional(rollbackFor = Exception.class)
    public void saveCommitPaperForScantron(PaperStudentWebVo pswvo) throws Exception{
        if(N_Utils.isEmptyInteger(pswvo.getEpid()) || N_Utils.isEmpty(pswvo.getExamno())){
            updateScanErrorInfo(4,pswvo);
            return;
        }

        //更加学生姓名和准考证号找到对应学生
        Integer userid = userMapper.getUseridByExamno(pswvo.getExamno());
        if(!N_Utils.isTrueInteger(userid)){
            updateScanErrorInfo(2,pswvo);
            return;
//            throw new Exception("考号有误");
        }
        //获取学生试卷
        EPaperStudent ps = ePaperStudentMapper.getPaperStudentByStuidAndEpid(pswvo.getEpid(),userid);

        //试卷不存在
        if(ps == null) {
            updateScanErrorInfo(3,pswvo);
            return;
//            throw new Exception("学生试卷不存在");
        }
        pswvo.setEpsid(ps.getEpsid());
        if(pswvo.getSstate() == 3){
            //说明学生缺考更新状态
            EPaperStudent paperStudent = new EPaperStudent();
            paperStudent.setEpsid(pswvo.getEpsid());
            paperStudent.setStupic(JSON.toJSONString(pswvo.getStupic()));
            paperStudent.setSstate(3);
            paperStudent.setBatchid(pswvo.getBatchid());
            if(N_Utils.isEmptyInteger(pswvo.getHasbad())){
                paperStudent.setHasbad(1);
            }else{
                paperStudent.setHasbad(0);
            }

            ePaperStudentMapper.updateStudentPaperState(paperStudent);
            ePaperStudentQuestionMapper.updateStuQuestionChecked(pswvo.getEpsid(),userid);
            eScanbatchMapper.updateQknum(pswvo.getBatchid());//更改缺考数量
            //更改违规数量
            if(paperStudent.getHasbad() == 1){
                eScanbatchMapper.updateWgnum(paperStudent.getBatchid());
            }
        }else{
            List<EPaperStudentQuestion> sqlist = pswvo.getQuestions();//学生提交试卷中试题

            //获取试卷中所有试题答案及分值
            List<PsqAnswerVo> anvolist = ePaperStudentQuestionMapper.listPaperQuestionsAnswer(pswvo.getEpsid());
            Integer checknum = 0;//记录试卷中试题批阅数量
            Double paperscore = 0D;//学生试卷得分
            for(EPaperStudentQuestion q : sqlist){
                q.setAnswertype(1);

                //获取该试题正确答案(根据题号区分)
                PsqAnswerVo anvo = anvolist.stream().filter(a -> a.getEptqid().equals(q.getEptqid())).findFirst().orElse(null);

                setCommitQuestion(q,anvo);
                if(q.getChecked() == 2){
                    checknum ++;
                }
                q.setEpsqid(anvo.getEpsqid());
                paperscore = ExamUtil.add(paperscore, q.getStuscore());
            }
            EPaperStudent paperStudent = new EPaperStudent();
            paperStudent.setEpsid(pswvo.getEpsid());
            paperStudent.setStupic(JSON.toJSONString(pswvo.getStupic()));
            paperStudent.setSstate(2);
            paperStudent.setStuscore(paperscore);
            paperStudent.setBatchid(pswvo.getBatchid());
            if(N_Utils.isEmptyInteger(pswvo.getHasbad())){
                paperStudent.setHasbad(1);
            }else{
                paperStudent.setHasbad(0);
            }

            int checked = 0;
            if(checknum == sqlist.size()){
                checked = 2;
            }
            paperStudent.setChecked(checked);

            ePaperStudentQuestionMapper.updateBatchStuQuestion(sqlist);
            ePaperStudentMapper.updateStudentPaper(paperStudent);
            //扫描完成更改批次数量
            eScanbatchMapper.updateScannum(paperStudent.getBatchid());
            //更改违规数量
            if(paperStudent.getHasbad() == 1){
                eScanbatchMapper.updateWgnum(paperStudent.getBatchid());
            }
            if(checked == 0){
                //获取试卷中需要合并图片的试题
                chandleStudentQuestionNoconvertedPic(pswvo.getEpsid(),2);
            }
        }
    }

    //更新扫描出错信息
    private void updateScanErrorInfo(Integer errortype,PaperStudentWebVo pswvo){
        //识别出错
        EScanerror er = new EScanerror();
        er.setBatchid(pswvo.getBatchid());
        er.setErrortype(errortype);
        er.setPagenum(pswvo.getPagenum());
        er.setErrorjson(JSON.toJSONString(pswvo));
        er.setCreatetime(N_Utils.getSecondTimestamp());
        eScanerrorMapper.insertSelective(er);
        eScanbatchMapper.updateErrornum(pswvo.getBatchid());
    }

    /**
     * @description 保存扫描出错信息
     * @param: [eScanerror]
     * @return: void
     * @author: wn
     * @date:
     **/
    public void saveScanPaperError(EScanerror eScanerror){
        eScanerror.setErrortype(1);
        eScanerror.setCreatetime(N_Utils.getSecondTimestamp());
        eScanerrorMapper.insertUseGeneratedKeys(eScanerror);
        eScanbatchMapper.updateErrornum(eScanerror.getBatchid());
    }

    /**
     * @Description 学生试卷作答得分
     * @Param [studentid, epid]
     * @Return java.util.Map
     * @Author wn
     * @Date 2022/8/12 10:45
     **/
    public Map getStudentPaperScore(Integer studentid,Integer epid){
        Map paper = ePaperStudentMapper.getStudentPaperScore(studentid,epid);
        Integer ptype = Integer.parseInt(paper.get("ptype").toString());
        Integer epsid = Integer.parseInt(paper.get("epsid").toString());
        List<Map> qtypeques = null;
        if(ptype == 1){
            qtypeques = ePaperStudentQuestionMapper.listQStuQuestionScore(epsid);
            setQuestionsForPaper(qtypeques);
        }else{
            qtypeques = ePaperStudentQuestionMapper.listFjStuQuestionScore(epsid);
        }
        paper.put("qtypes",qtypeques);
        return paper;
    }

    private void setQuestionsForPaper(List<Map> qtypes){
        for(Map mt : qtypes){
            Integer ctype = Integer.parseInt(mt.get("ctype").toString());
            if(ctype == 11 || ctype == 12){
                List<Map> questions = (List<Map>) mt.get("questions");
                Map<String,List<Map>> quemap = questions.stream().collect(Collectors.groupingBy(o -> o.get("questionpid").toString()));
                List<Map> mqlist = new ArrayList<>();
                for(Map.Entry<String,List<Map>> entry : quemap.entrySet()){
                    List<Map> sonqlst = entry.getValue();
                    Double sontotalsocre = sonqlst.stream().mapToDouble(o -> Double.parseDouble(o.get("score").toString())).sum();
                    Map sque = sonqlst.get(0);
                    Map mque = new HashMap();
                    mque.put("questionid",sque.get("mquestionid").toString());
                    mque.put("qlevel",2);
                    mque.put("qstem",sque.get("mqstem").toString());
                    mque.put("ctype",Integer.parseInt(sque.get("mctype").toString()));
                    mque.put("qtypeid",sque.get("mqtypeid").toString());
                    mque.put("qtypename",sque.get("mqtypename").toString());
                    mque.put("qorder",sque.get("qorder").toString());
                    mque.put("qn",sque.get("qn").toString());
                    mque.put("snum",Integer.parseInt(sque.get("snum").toString()));
                    if(ctype == 12 && sque.get("mhearfile")!=null){
                        mque.put("hearfile",sque.get("mhearfile").toString());
                    }else{
                        mque.put("hearfile","");
                    }
                    mque.put("score",sontotalsocre);
                    mque.put("sonques",sonqlst);
                    mqlist.add(mque);
                }

                mt.put("questions",mqlist);

            }
        }
    }

}
