package com.xhkjedu.sexam.service.paper;

import com.alibaba.fastjson.JSON;
import com.xhkjedu.exception.MissingParametersException;
import com.xhkjedu.sexam.mapper.exam.EBaseMapper;
import com.xhkjedu.sexam.mapper.paper.EPaperCorrectTeacherMapper;
import com.xhkjedu.sexam.mapper.paperstudent.EPaperStudentMapper;
import com.xhkjedu.sexam.mapper.system.UserMapper;
import com.xhkjedu.sexam.model.paperstudent.EPaperStudentQuestion;
import com.xhkjedu.vo.exam.EPCTeacherVo;
import com.xhkjedu.sexam.vo.paper.EPaperSQuestionVo;
import com.xhkjedu.vo.exam.EPaperVo;
import com.xhkjedu.utils.N_Utils;
import com.xhkjedu.vo.ResultVo;
import com.xhkjedu.vo.system.UserVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

@Service
@Slf4j
public class EPaperCorrectTeacherService {
    //ReentrantLock(boolean) true为公平锁，默认false不公平锁，性能更好，可以插队！
    Lock lock = new ReentrantLock();
    @Resource
    private EPaperCorrectTeacherMapper correctTeacherMapper;
    @Resource
    private EBaseMapper eBaseMapper;
    @Resource
    private UserMapper userMapper;
    @Resource
    private EPaperStudentMapper ePaperStudentMapper;

    //待阅卷列表
    public List<Map> listPending(Integer teacherid) {
        return correctTeacherMapper.listPending(teacherid);
    }

    //已阅卷列表
    public List<Map> listMarked(Integer teacherid) {
        return correctTeacherMapper.listMarked(teacherid);
    }

    //随机获取待批试题
    public ResultVo getCorrectQuestion(Integer teacherid, Integer eptqid, String classids, Integer esid
            , Integer epsqid, List<Integer> eptqids) {
        //Integer examstate = eBaseMapper.getExamStateByEsId(esid);
        //if (2 <= examstate) throw new MissingParametersException("考试已结束禁止操作");
        lock.lock();
        Map map = new HashMap();
        String msg = "获取成功";
        try {
            //随机获取一条待批阅试题
            EPaperSQuestionVo sq;
            int timestamp = N_Utils.getSecondTimestamp();
            if(N_Utils.isEmptyInteger(eptqid)) {//没指定题返回考试信息
                map = correctTeacherMapper.getExamNameByEsId(esid);//根据考试科目id获取考试名称
                sq = correctTeacherMapper.getCorrectQuestion2(teacherid, eptqids, classids);
                if (sq != null) {
                    eptqid = sq.getEptqid();
                    //修改试卷学生试题为批阅中
                    correctTeacherMapper.updateCheckQuestionById(sq.getEpsqid(), teacherid, timestamp);
                }
            } else {
                sq = correctTeacherMapper.getCorrectQuestion(teacherid, eptqid, classids, null, 1);
            }
            if (sq == null) {
                sq = correctTeacherMapper.getCorrectQuestion(teacherid, eptqid, classids, epsqid, 2);//已批改记录
                if (sq == null && N_Utils.isListNotEmpty(eptqids)) {
                    sq = correctTeacherMapper.getCorrectQuestion2(teacherid, eptqids, classids);
                    if (sq != null) {
                        eptqid = sq.getEptqid();
                        //修改试卷学生试题为批阅中
                        correctTeacherMapper.updateCheckQuestionById(sq.getEpsqid(), teacherid, timestamp);
                    }
                }
                if (sq == null) {
                    msg = "已经是最后一条";
                }
            } else {
                //修改试卷学生试题为批阅中
                correctTeacherMapper.updateCheckQuestionById(sq.getEpsqid(), teacherid, timestamp);
            }
            map.put("sq", sq);//学生待批试题
            //试题批阅情况
            EPaperSQuestionVo q = correctTeacherMapper.getCheckQuestion(eptqid, teacherid, classids);
            Integer tjnum = q.getTjnum();
            Integer pynum = q.getPynum();
            map.put("tjnum", tjnum);//提交人数
            map.put("pynum", pynum);//批阅人数
            map.put("wpynum", q.getWpynum());//我批阅人数
            map.put("pyrate", N_Utils.getIntegerDivideAndMulitiply(pynum, tjnum));//批阅进度
        } catch (Exception e) {
            log.error("随机获取待批试题出错", e.getMessage());
            throw new MissingParametersException("随机获取待批试题出错:" + e.getMessage());
        } finally {
            lock.unlock();
        }
        return new ResultVo(0, msg, map);
    }

    //获取上一份批阅试题
    public ResultVo getPreQuestion(Integer eptqid, Integer teacherid, Integer esid, String classids, Integer epsqid) {
        EPaperSQuestionVo sq;
        String msg = "获取成功";
        if(N_Utils.isEmptyInteger(epsqid)) {
            sq = correctTeacherMapper.getPreQuestion(eptqid, teacherid);
            if (sq == null) return new ResultVo(1, "您还没有批阅记录");
        } else {
            sq = correctTeacherMapper.getCheckedQuestion(teacherid, epsqid);
            if (sq == null) msg = "已经是第一条";
        }
        Map map = correctTeacherMapper.getExamNameByEsId(esid);//根据考试科目id获取考试名称
        //试题批阅情况
        EPaperSQuestionVo q = correctTeacherMapper.getCheckQuestion(eptqid, teacherid, classids);
        Integer tjnum = q.getTjnum();
        Integer pynum = q.getPynum();
        map.put("sq", sq);//学生待批试题
        map.put("tjnum", tjnum);//提交人数
        map.put("pynum", pynum);//批阅人数
        map.put("wpynum", q.getWpynum());//我批阅人数
        map.put("pyrate", N_Utils.getIntegerDivideAndMulitiply(pynum, tjnum));//批阅进度
        return new ResultVo(0, msg, map);
    }

    //阅卷记录
    public List<Map> listRecord(Integer eptqid, Integer teacherid) {
        return correctTeacherMapper.listRecord(eptqid, teacherid);
    }

    //批阅试题
    @Async("asyncPoolTaskExecutor")
    public Future<ResultVo> correctQuestion(EPaperStudentQuestion psq) {
        try {
            Integer epsid = psq.getEpsid();
            //Integer examstate = ePaperStudentMapper.getExamStateByEpsId(epsid);
            //if (2 <= examstate) throw new MissingParametersException("考试已结束禁止操作");

            //获取当前试题批阅状态，如果为已批改，不处理（2024-06-26产品确认添加）
            //Integer checked = correctTeacherMapper.getCorrectQuestionState(psq.getEpsqid());
            //if(checked != 2){
                int timestamp = N_Utils.getSecondTimestamp();
                psq.setChecktime(timestamp);

                correctTeacherMapper.correctQuestion(psq);
                Integer num = correctTeacherMapper.getNotCorrect(epsid);//学生未批改试题数量
                if (num == 0) {//批阅完成修改学生试卷批阅状态
                    correctTeacherMapper.updateCheckStuById(epsid, psq.getCheckid());
                }
            //}
            //试卷批阅进度
            double pyrate = 0;
            if (N_Utils.isListNotEmpty(psq.getEptqids())) {
                EPaperSQuestionVo vo = correctTeacherMapper.getPaperCheck(psq);
                pyrate = N_Utils.getIntegerDivideAndMulitiply(vo.getPynum(), vo.getTjnum());
            }
            return new AsyncResult<>(new ResultVo(0, "批阅成功", pyrate));
        } catch (Exception e) {
            return new AsyncResult<>(new ResultVo(1, e.getMessage()));
        }
    }

    //阅卷进度
    public Map markProgress(Integer examid) {
        Map map = eBaseMapper.findById2(examid);
        List<EPaperVo> papers = correctTeacherMapper.listPaperByExamId(examid);//获取考试试卷
        String epids = papers.stream().map(p -> p.getEpid().toString()).collect(Collectors.joining(","));
        List<EPaperStudentQuestion> questions = correctTeacherMapper.listStuQuestionByEpids(epids);//获取考试学生试题

        List<EPaperStudentQuestion> pyList = questions.stream().filter(q -> !N_Utils.isEmptyInteger(q.getCheckid()))
                .collect(Collectors.toList());
        //List<Integer> userids = pyList.stream().map(q -> q.getCheckid()).distinct().collect(Collectors.toList());
        List<Integer> userids = new ArrayList<>();
        List<EPCTeacherVo> cteachers = new ArrayList<>();
        for (EPaperVo paper : papers) {
            if (paper.getCorrecttype() == 0) continue;
            List<EPCTeacherVo> teachers = JSON.parseArray(paper.getCorrectJson(), EPCTeacherVo.class);
            paper.setCorrectJson(null);
            teachers.forEach(t -> {
                userids.add(t.getTeacherid());
                t.setEpid(paper.getEpid());
                t.setCorrecttype(paper.getCorrecttype());
                cteachers.add(t);
            });
        }
        Map<Integer, String> teacherMap = new HashMap<>();
        if (N_Utils.isListNotEmpty(userids)) {
            List<UserVo> teachers = userMapper.listNameByUserIds(userids);//根据用户ids查找用户姓名
            teacherMap = teachers.stream().collect(Collectors.toMap(u -> u.getUserid(), u -> u.getUsername()));
        }
        for (EPaperStudentQuestion q : pyList) {
            if (q.getChecked() != 2) continue;
            q.setCheckname(teacherMap.get(q.getCheckid()));//批阅人
        }
        for (EPCTeacherVo cteacher : cteachers) {
            cteacher.setTeachername(teacherMap.get(cteacher.getTeacherid()));
        }

        for (EPaperVo paper : papers) {
            //单科统计
            Integer epid = paper.getEpid();
            List<EPaperStudentQuestion> qlist =
                    questions.stream().filter(q -> q.getEpid().equals(epid)).collect(Collectors.toList());
            if (N_Utils.isListEmpty(qlist)) {
                List<Map> questionList = correctTeacherMapper.listQnByEpId(epid);//获取试卷试题题号
                for (Map q : questionList) {
                    q.put("stunum", 0);
                    q.put("pynum", 0);
                    q.put("pyrate", 0);
                    q.put("checkname", "");
                }
                paper.setQuestions(questionList);
                continue;
            }
            List<Integer> qtlist = qlist.stream().filter(q -> !N_Utils.isObjectiveQuestion(q.getCtype()))
                    .map(q -> q.getQorder()).distinct().collect(Collectors.toList());
            List<EPaperStudentQuestion> zdlist =//作答集合
                    qlist.stream().filter(q -> q.getAnswered().equals(1)).collect(Collectors.toList());
            List<EPaperStudentQuestion> pylist =//批阅集合
                    zdlist.stream().filter(q -> q.getChecked().equals(2)).collect(Collectors.toList());
            Integer zgtnum = qtlist.size();
            Integer stunum = zdlist.stream().map(q -> q.getStudentid()).distinct().collect(Collectors.toList()).size();
            Integer zpynum = pylist.size();//试卷批阅试题数量
            paper.setZgtnum(zgtnum);//主观题数量
            paper.setStunum(stunum);//实际人数
            paper.setPyrate(N_Utils.getIntegerDivideAndMulitiply(zpynum, zdlist.size()));//批阅进度

            Integer correcttype = paper.getCorrecttype();
            String checkname = null;
            if (correcttype == 1) {
                checkname = cteachers.stream().filter(q -> epid.equals(q.getEpid()))
                        .map(q -> q.getTeachername()).distinct().sorted().collect(Collectors.joining("、"));
            }
            //单题统计
            List<Map> questionList = new ArrayList<>();
            for (Integer qorder : qtlist) {
                List<EPaperStudentQuestion> qslist =
                        qlist.stream().filter(q -> q.getQorder().equals(qorder)).collect(Collectors.toList());
                zdlist = qslist.stream().filter(q -> q.getAnswered().equals(1)).collect(Collectors.toList());
                stunum = zdlist.size();
                Integer pynum = zdlist.stream().filter(q -> q.getChecked().equals(2)).collect(Collectors.toList()).size();
                Map question = new HashMap();
                question.put("qn", qslist.stream().sorted(Comparator.comparing(q -> q.getEptqid()))
                        .map(q -> q.getQn()).distinct().collect(Collectors.joining(",")));//题号
                question.put("qorder", qorder);//试题排序
                question.put("pynum", pynum);//已阅题数
                question.put("stunum", stunum);//参与人数
                question.put("pyrate", N_Utils.getIntegerDivideAndMulitiply(pynum, stunum));//批阅进度
                if(correcttype==2){
                    List<Integer> eptqids = qslist.stream().map(q -> q.getEptqid()).distinct().collect(Collectors.toList());
                    checkname = cteachers.stream().filter(q -> q.getEptqid() != null && N_Utils.numInList(q.getEptqid(), eptqids))
                            .map(q -> q.getTeachername()).distinct().sorted().collect(Collectors.joining("、"));
                }
                question.put("checkname", checkname);//阅卷教师
                questionList.add(question);
            }
            paper.setQuestions(questionList);

            //阅卷教师统计
            List<Map> teacherList = new ArrayList<>();
            Map<Integer, List<EPaperStudentQuestion>> tcollect =
                    pylist.stream().filter(q -> q.getCheckid() != null && q.getChecked() == 2)
                            .collect(Collectors.groupingBy(q -> q.getCheckid()));
            for (Map.Entry<Integer, List<EPaperStudentQuestion>> entry : tcollect.entrySet()) {
                List<EPaperStudentQuestion> list = entry.getValue();
                stunum = list.stream().filter(q -> q.getAnswered().equals(1))
                        .map(q -> q.getStudentid()).distinct().collect(Collectors.toList()).size();
                Integer wpynum = list.size();
                Map teacher = new HashMap();
                teacher.put("checkname", list.get(0).getCheckname());//教师姓名
                teacher.put("stunum", stunum);//参与人数
                teacher.put("wpynum", wpynum);//批阅人数
                teacher.put("zpynum", zpynum);//总批阅人数
                teacher.put("pyrate", N_Utils.getIntegerDivideAndMulitiply(wpynum, zpynum));//批阅进度
                String qn = list.stream().sorted(Comparator.comparing(q -> q.getEptqid()))
                        .map(q -> q.getQn()).distinct().collect(Collectors.joining(","));
                teacher.put("qn", qn);//阅卷题号
                teacherList.add(teacher);
            }
            paper.setTeachers(teacherList);
        }
        map.put("papers", papers);
        return map;
    }

    //随机获取待批试题2
    public ResultVo getCorrectQuestion2(Integer teacherid, Integer esid, List<Integer> eptqids, String classids) {
        //Integer examstate = eBaseMapper.getExamStateByEsId(esid);
        //if (2 <= examstate) throw new MissingParametersException("考试已结束禁止操作");
        lock.lock();
        Map map = correctTeacherMapper.getExamNameByEsId(esid);//根据考试科目id获取考试名称
        String msg = "获取成功";
        try {
            int timestamp = N_Utils.getSecondTimestamp();
            //随机获取一条待批阅试题
            EPaperSQuestionVo sq = correctTeacherMapper.getCorrectQuestion2(teacherid, eptqids, classids);
            if (sq == null) {
                //获取第一条批改试题
                sq = correctTeacherMapper.getCheckedQuestion2(eptqids, teacherid);
                map.put("sq", sq);//学生已批试题
                if (sq == null) {
                    msg = "没有您的批阅记录";
                }
            } else {
                map.put("sq", sq);//学生待批试题
                //修改试卷学生试题为批阅中
                correctTeacherMapper.updateCheckQuestionById(sq.getEpsqid(), teacherid, timestamp);
            }
            if (sq != null) {
                //试题批阅情况
                EPaperSQuestionVo q = correctTeacherMapper.getCheckQuestion(sq.getEptqid(), teacherid, classids);
                Integer tjnum = q.getTjnum();
                Integer pynum = q.getPynum();
                map.put("tjnum", tjnum);//提交人数
                map.put("pynum", pynum);//批阅人数
                map.put("wpynum", q.getWpynum());//我批阅人数
                map.put("pyrate", N_Utils.getIntegerDivideAndMulitiply(pynum, tjnum));//批阅进度
            }
        } catch (Exception e) {
            log.error("随机获取待批试题出错", e.getMessage());
            throw new MissingParametersException("随机获取待批试题出错:" + e.getMessage());
        } finally {
            lock.unlock();
        }
        return new ResultVo(0, msg, map);
    }

    //取消试题锁定
    public void unLockAllQuestion(Integer teacherid) {
        final ExecutorService exec = Executors.newFixedThreadPool(1);
        try {
            Callable call = new Callable() {
                @Override
                public String call() throws IOException {
                    correctTeacherMapper.unLockAllQuestion(teacherid);
                    return "执行成功";
                }
            };
            Future<String> future = exec.submit(call);
            future.get(10, TimeUnit.SECONDS); //任务处理超过10s关闭
        } catch (Exception e) {
            log.error("取消试题锁定失败", e.getMessage());
        }
        // 关闭线程池
        exec.shutdown();
    }

    /**
     * @Description 获取待阅卷数量
     * @Date 2024/9/18 10:35
     * @Author YWX
     * @Param [teacherid]
     * @Return java.lang.Integer
     **/
    public Integer getPendingNum(Integer teacherid) {
        return correctTeacherMapper.getPendingNum(teacherid);
    }
}
