package com.ruoyi.project.training.elearn.service.impl;

import com.ruoyi.common.jpush.JiGuangPushService;
import com.ruoyi.framework.job.service.JobService;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.project.system.mapper.SysUserMapper;
import com.ruoyi.project.training.bccnew.domain.TTsFirstplan;
import com.ruoyi.project.training.bccnew.domain.TTsNew;
import com.ruoyi.project.training.bccnew.service.ITTsFirstplanService;
import com.ruoyi.project.training.bccnew.service.ITTsNewService;
import com.ruoyi.project.training.domain.TTrainingbcc;
import com.ruoyi.project.training.domain.TTrainingbccDevice;
import com.ruoyi.project.training.elearn.domain.*;
import com.ruoyi.project.training.elearn.mapper.*;
import com.ruoyi.project.training.elearn.service.ITElPaperService;
import com.ruoyi.project.training.mapper.TTrainingbccDeviceMapper;
import com.ruoyi.project.training.mapper.TTrainingbccMapper;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 在线考试Service业务层处理
 *
 * @author ssy
 * @date 2024-05-29
 */
@Service
public class TElPaperServiceImpl implements ITElPaperService {
    /**
     * 展示的选项，ABC这样
     */
    private static List<String> ABC = Arrays.asList(new String[]{
            "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X"
            , "Y", "Z"
    });
    protected final Logger logger = LoggerFactory.getLogger(BaseController.class);
    @Resource
    private TElPaperMapper tElPaperMapper;
    @Resource
    private TElPaperQuMapper tElPaperQuMapper;
    @Resource
    private TElPaperQuAnswerMapper tElPaperQuAnswerMapper;
    @Autowired
    private JobService jobService;
    @Resource
    private TElExamMapper tElExamMapper;
    @Resource
    private TElQuMapper tElQuMapper;
    @Resource
    private TElQuAnswerMapper tElQuAnswerMapper;
    @Resource
    private TElExamRepoMapper tElExamRepoMapper;
    @Resource
    private TElUserExamMapper tElUserExamMapper;
    @Resource
    private TElUserBookMapper tElUserBookMapper;
    @Resource
    private SysUserMapper sysUserMapper;
    @Resource
    private ITTsFirstplanService tsFirstplanService;
    @Resource
    private ITTsNewService tsNewService;
    @Autowired
    private ITTsFirstplanService tTsFirstplanService;
    @Resource
    private TTrainingbccMapper tTrainingbccMapper;
    @Resource
    private TTrainingbccDeviceMapper tTrainingbccDeviceMapper;
    @Resource
    private JiGuangPushService jiGuangPushService;

    /**
     * 查询在线考试
     *
     * @param paperId 在线考试ID
     * @return 在线考试
     */
    @Override
    public TElPaper selectTElPaperById(Long paperId) {
        return tElPaperMapper.selectTElPaperById(paperId);
    }

    /**
     * 查询在线考试列表
     *
     * @param tElPaper 在线考试
     * @return 在线考试
     */
    @Override
    public List<TElPaper> selectTElPaperList(TElPaper tElPaper) {
        return tElPaperMapper.selectTElPaperList(tElPaper);
    }

    /**
     * 新增在线考试
     *
     * @param tElPaper 在线考试
     * @return 结果
     */
    @Override
    public int insertTElPaper(TElPaper tElPaper) {
        return tElPaperMapper.insertTElPaper(tElPaper);
    }

    /**
     * 修改在线考试
     *
     * @param tElPaper 在线考试
     * @return 结果
     */
    @Override
    public int updateTElPaper(TElPaper tElPaper) {
        return tElPaperMapper.updateTElPaper(tElPaper);
    }

    /**
     * 批量删除在线考试
     *
     * @param paperIds 需要删除的在线考试ID
     * @return 结果
     */
    @Override
    public int deleteTElPaperByIds(Long[] paperIds) {
        return tElPaperMapper.deleteTElPaperByIds(paperIds);
    }

    /**
     * 删除在线考试信息
     *
     * @param paperId 在线考试ID
     * @return 结果
     */
    @Override
    public int deleteTElPaperById(Long paperId) {
        return tElPaperMapper.deleteTElPaperById(paperId);
    }

    @Override
    @Transactional
    public TElPaper createPaper(TElPaper tElPaper, Long userId) {
        // 查找考试
        TElExam exam = tElExamMapper.selectTElExamById(tElPaper.getExamId());

        // 考试题目列表
        List<TElPaperQu> paperQuList = new ArrayList<>();
        TElExamRepo tElExamRepo = new TElExamRepo();
        tElExamRepo.setExamId(tElPaper.getExamId());
        List<TElExamRepo> examRepoList = tElExamRepoMapper.selectTElExamRepoList(tElExamRepo);
        try {
            for (TElExamRepo item : examRepoList
            ) {
                // 单选题
                if (item.getRadioCount() > 0) {
                    item.setQuType(1);
                    List<TElQu> radioListAll = tElQuMapper.selectTElQuListByRepo(item);
                    Collections.shuffle(radioListAll);
                    List<TElQu> radioList = radioListAll.subList(0, Integer.parseInt(String.valueOf(item.getRadioCount())));
                    for (TElQu qu : radioList
                    ) {
                        TElPaperQu paperQu = this.processPaperQu(item, qu);
                        paperQuList.add(paperQu);
                    }
                }
                // 多选题
                if (item.getMultiCount() > 0) {
                    item.setQuType(2);
                    List<TElQu> multiListAll = tElQuMapper.selectTElQuListByRepo(item);
                    Collections.shuffle(multiListAll);
                    List<TElQu> multiList = multiListAll.subList(0, Integer.parseInt(String.valueOf(item.getMultiCount())));
                    for (TElQu qu : multiList
                    ) {
                        TElPaperQu paperQu = this.processPaperQu(item, qu);
                        paperQuList.add(paperQu);
                    }
                }
                // 判断题
                if (item.getJudgeCount() > 0) {
                    item.setQuType(3);
                    List<TElQu> judgeListAll = tElQuMapper.selectTElQuListByRepo(item);
                    Collections.shuffle(judgeListAll);
                    List<TElQu> judgeLis = judgeListAll.subList(0, Integer.parseInt(String.valueOf(item.getJudgeCount())));
                    for (TElQu qu : judgeLis
                    ) {
                        TElPaperQu paperQu = this.processPaperQu(item, qu);
                        paperQuList.add(paperQu);
                    }
                }
            }
            //通过 Comparator.comparingInt() 直接提取 quType 属性值，并按其自然升序排列（即 1 → 2 → 3）：
            paperQuList.sort(Comparator.comparingLong(TElPaperQu::getQuType));
        } catch (IndexOutOfBoundsException e) {
            throw new IndexOutOfBoundsException("题库无法匹配");
        }



        //保存试卷基本信息
        TElPaper paper = new TElPaper();
        paper.setExamId(exam.getExamId());
        paper.setTitle(exam.getTitle());
        paper.setTotalScore(exam.getTotalScore());
        paper.setTotalTime(exam.getTotalTime());
        paper.setUserScore(0l);
        paper.setUserId(userId);
        paper.setCreateTime(new Date());
        paper.setUpdateTime(new Date());
        paper.setQualifyScore(exam.getQualifyScore());
        paper.setState(0l);
        paper.setHasSaq(0l);

        // 截止时间
        Calendar cl = Calendar.getInstance();
        cl.setTimeInMillis(System.currentTimeMillis());
        cl.add(Calendar.MINUTE, exam.getTotalTime().intValue());
        paper.setLimitTime(cl.getTime());
        tElPaperMapper.insertTElPaper(paper);
        // 保存试卷试题列表
        this.savePaperQu(paper.getPaperId(), paperQuList);

        String jobName = "break_exam_" + tElPaper.getPaperId();
//        jobService.addCronJob(BreakExamJob.class, jobName, this.dateToCron(tElPaper.getLimitTime()),String.valueOf(tElPaper.getPaperId()));

        return paper;
    }

    @Override
    @Transactional
    public void fillAnswer(TElPaperQu paperQu) {
        // 未作答
        if (CollectionUtils.isEmpty(paperQu.getAnswers())
                && StringUtils.isBlank(paperQu.getAnswer())) {
            return;
        }
        TElPaperQuAnswer param = new TElPaperQuAnswer();
        param.setQuId(paperQu.getQuId());
        param.setPaperId(paperQu.getPaperId());
        List<TElPaperQuAnswer> paperQuAnswers = tElPaperQuAnswerMapper.selectTElPaperQuAnswerList(param);

        //是否正确
        long right = 1;

        //更新正确答案
        for (TElPaperQuAnswer item : paperQuAnswers) {

            if (paperQu.getAnswers().contains(String.valueOf(item.getId()))) {
                item.setChecked(1l);
            } else {
                item.setChecked(0l);
            }
            //有一个对不上就是错的
            if (item.getIsRight() != null && !item.getIsRight().toString().equals(item.getChecked().toString())) {
                right = 0;
            }
            tElPaperQuAnswerMapper.updateTElPaperQuAnswer(item);
        }
        //修改为已回答
        TElPaperQu qu = new TElPaperQu();
        qu.setQuId(paperQu.getQuId());
        qu.setPaperId(paperQu.getPaperId());
        qu.setIsRight(right);
        qu.setAnswer(paperQu.getAnswer());
        qu.setAnswered(1l);
        tElPaperQuMapper.updateTElPaperQuByKey(qu);
    }

    @Override
    @Transactional
    public void handExam(TElPaperQu paperQu) {
        TElPaper paper = tElPaperMapper.selectTElPaperById(paperQu.getPaperId());

        // 客观分
        int objScore = tElPaperQuMapper.sumObjective(paperQu.getPaperId());
        paper.setObjScore((long) objScore);
        paper.setUserScore((long) objScore);
        SysUser user = sysUserMapper.selectUserById(paper.getUserId());

        // 主观分，因为要阅卷，所以给0
        paper.setSubjScore(0l);
        // 待阅卷
        if (paper.getHasSaq() == 1) {

        } else {
            // 同步保存考试成绩
            TElUserExam record = tElUserExamMapper.selectTElUserExamByPaPer(paper);
            long pass = objScore >= paper.getQualifyScore() ? 1 : 0;
            if (record == null) {
                record = new TElUserExam();
                record.setUserId(paper.getUserId());
                record.setExamId(paper.getExamId());
                record.setTitle(paper.getTitle());
                record.setMaxScore((long) objScore);
                record.setTryCount(1l);
                record.setPassed(pass);
                record.setUpdatedate(new Date());
                record.setUserName(user.getNickName());
                tElUserExamMapper.insertTElUserExam(record);
            } else {
                // 修复低分数不加入统计问题
                record.setTryCount(record.getTryCount() + 1);
                record.setUpdatedate(new Date());
                record.setUserName(user.getNickName());
                if (record.getMaxScore() < objScore) {
                    record.setMaxScore((long) objScore);
                    record.setPassed(pass);
                }
                tElUserExamMapper.updateTElUserExam(record);
            }
            paper.setState(2l);
        }
        paper.setUpdateTime(new Date());

        //计算考试时长
        Calendar cl = Calendar.getInstance();
        cl.setTimeInMillis(System.currentTimeMillis());
        int userTime = (int) ((System.currentTimeMillis() - paper.getCreatedate().getTime()) / 1000 / 60);
        if (userTime == 0) {
            userTime = 1;
        }
        paper.setUserTime((long) userTime);
        //更新试卷
        tElPaperMapper.updateTElPaper(paper);

        new Thread(() -> {
            //错题本
            TElPaperQu param = new TElPaperQu();
            param.setPaperId(paperQu.getPaperId());
            param.setIsRight(0l);
            List<TElPaperQu> quList = tElPaperQuMapper.selectTElPaperQuList(param);
            for (TElPaperQu i : quList) {
                TElUserBook quey = new TElUserBook();
                quey.setUserId(paper.getUserId());
                quey.setExamId(paper.getExamId());
                quey.setQuId(i.getQuId());
                List<TElUserBook> books = tElUserBookMapper.selectTElUserBookList(quey);
                TElQu qu = tElQuMapper.selectTElQuById(i.getQuId());

                if (books.size() == 0) {
                    TElUserBook book = new TElUserBook();
                    book.setExamId(paper.getExamId());
                    book.setUserId(paper.getUserId());
                    book.setTitle(qu.getContent());
                    book.setQuId(i.getQuId());
                    book.setWrongCount(1l);
                    book.setUpdatedate(new Date());
                    tElUserBookMapper.insertTElUserBook(book);
                } else {
                    TElUserBook book = books.get(0);
                    book.setUpdatedate(new Date());
                    book.setWrongCount(book.getWrongCount() + 1);
                    tElUserBookMapper.updateTElUserBook(book);
                }
            }
        }, "错题本").start();

        TElExam exam = tElExamMapper.selectTElExamById(paper.getExamId());
        if (exam.getExamType() == 2) {
            new Thread(() -> {

                TTrainingbcc param = new TTrainingbcc();
                logger.info("===================" + paper.getExamId());
                logger.info("++++++++++++++++++++++" + exam.getExamId());
                param.setExamId(paper.getExamId());
                List<TTrainingbcc> tTrainingbccList = tTrainingbccMapper.selectTTrainingbccList(param);
                if (!CollectionUtils.isEmpty(tTrainingbccList)) {
                    for (TTrainingbcc t : tTrainingbccList
                    ) {
                        TTrainingbccDevice device = new TTrainingbccDevice();
                        device.setRegularId(t.getId());
                        device.setStaffId(user.getStaffId());
                        List<TTrainingbccDevice> deviceList = tTrainingbccDeviceMapper.selectTTrainingbccDeviceList(device);
                        if (!CollectionUtils.isEmpty(deviceList)) {
                            for (TTrainingbccDevice d : deviceList
                            ) {
                                long pass = objScore >= paper.getQualifyScore() ? 1 : 0;
                                d.setExamState(pass);
                                d.setExamNum(d.getExamNum() + 1);
                                if (d.getExamNum() >= 5) {
                                    d.setExamState(-1l);
                                }
                                d.setExamDate(new Date());
                                tTrainingbccDeviceMapper.updateTTrainingbccDevice(d);
                            }
                        }
                    }
                }

            }, "装置培训考试成绩").start();
        } else if (exam.getExamType() == 3) {
            new Thread(() -> {
                TTsNew tTsNew = new TTsNew();
                tTsNew.setPlanStatus(0L);
                tTsNew.setStaffId(user.getStaffId());
                List<TTsNew> tTsNews = tsNewService.selectTTsNewList(tTsNew);
                if (!CollectionUtils.isEmpty(tTsNews)) {
                    TTsFirstplan tTsFirstplan = new TTsFirstplan();
                    tTsFirstplan.setExamId(paper.getExamId());
                    TTsNew tsNew = tTsNews.get(0);
                    tTsFirstplan.setNewId(tsNew.getNewId());
                    for (TTsFirstplan tsFirstplan : tsFirstplanService.selectTTsFirstplanList(tTsFirstplan)) {
                        if (tsFirstplan.getExamType().equals("线上考试")) {
                            String score = "";
                            boolean flag = false;
                            if (paper.getUserScore() >= paper.getQualifyScore()) {
                                if (StringUtils.isEmpty(tsFirstplan.getScore1())) {
                                    tsFirstplan.setScore1("合格");
                                } else if (StringUtils.isEmpty(tsFirstplan.getScore2())) {
                                    tsFirstplan.setScore2("合格");
                                }
                                score = "合格";
                                flag = true;
                                tsFirstplan.setPlanStatus(5L);
                            } else {
                                if (StringUtils.isEmpty(tsFirstplan.getScore1())) {
                                    tsFirstplan.setScore1("不合格");
                                } else if (tsFirstplan.getScore1().equals("不合格") && StringUtils.isEmpty(tsFirstplan.getScore2())) {
                                    tsFirstplan.setScore2("不合格");
                                    flag = true;
                                }
                                score = "不合格";
                            }
                            tsFirstplan.setUserId(user.getUserId());
                            tsFirstplan.setNickName(user.getNickName());
                            logger.info("====tsFirstplan:{}", tsFirstplan);
                            tTsFirstplanService.updateTTsFirstplan(tsFirstplan);

                            if (flag) {
                                SysUser sysUser = new SysUser();
                                sysUser.setNickName(tsFirstplan.getTrainer());
                                for (SysUser trainer : sysUserMapper.selectUserList(sysUser)) {
                                    sysUser = new SysUser();
                                    SysUser staff = sysUserMapper.selectUserByStaffId(tTsNew.getStaffId());
                                    jiGuangPushService.send("导师带徒-装置级培训", staff.getNickName() + "的" + tsFirstplan.getTopic() + "成绩为" + score + "，请确认成绩。", trainer.getUserId().toString());
                                }
                            }
                        }
                    }
                }
            }, "导师带徒-装置级培训考试成绩").start();
        }
    }

    @Override
    public TElPaper paperResult(TElPaperQu paperQu) {
        TElPaper paper = tElPaperMapper.selectTElPaperById(paperQu.getPaperId());
        TElPaperQu query = new TElPaperQu();
        query.setPaperId(paperQu.getPaperId());
        List<TElPaperQu> quList = tElPaperQuMapper.selectTElPaperQuListByPaper(query);
        for (TElPaperQu item : quList
        ) {
            TElPaperQuAnswer a = new TElPaperQuAnswer();
            a.setPaperId(paperQu.getPaperId());
            a.setQuId(item.getQuId());
            List<TElPaperQuAnswer> list = tElPaperQuAnswerMapper.selectTElPaperQuAnswerListByPaper(a);
            item.setAnswerList(list);
        }
        //
        SysUser user = sysUserMapper.selectUserById(paper.getUserId());
        paper.setNickName(user.getNickName());
        paper.setQuList(quList);
        return paper;
    }

    /**
     * 保存试卷试题列表
     *
     * @param paperId
     * @param quList
     */
    private void savePaperQu(Long paperId, List<TElPaperQu> quList) {
        List<TElPaperQu> batchQuList = new ArrayList<>();
        List<TElPaperQuAnswer> batchAnswerList = new ArrayList<>();
        long sort = 0;
        TElQuAnswer qury = new TElQuAnswer();
        //线程池

        for (TElPaperQu item : quList) {
            item.setPaperId(paperId);
            item.setSort(sort);
            qury.setQuId(item.getQuId());
            //回答列表
            List<TElQuAnswer> answerList = tElQuAnswerMapper.selectTElQuAnswerList(qury);
            Collections.shuffle(answerList);
            if (!CollectionUtils.isEmpty(answerList)) {

                long ii = 0;
                for (TElQuAnswer answer : answerList) {
                    TElPaperQuAnswer paperQuAnswer = new TElPaperQuAnswer();
                    paperQuAnswer.setPaperId(paperId);
                    paperQuAnswer.setQuId(answer.getQuId());
                    paperQuAnswer.setAnswerId(answer.getAnswerId());
                    paperQuAnswer.setChecked(0l);
                    paperQuAnswer.setSort(ii);
                    paperQuAnswer.setAbc(ABC.get((int) ii));
                    paperQuAnswer.setIsRight(answer.getIsRight());
                    ii++;
                    batchAnswerList.add(paperQuAnswer);
                }
            }
            batchQuList.add(item);
            sort++;
        }
        //添加问题
        //线程池
        ExecutorService executorService = Executors.newFixedThreadPool(1);
        final CountDownLatch latch = new CountDownLatch(quList.size()); //相同线程数量的计数

        for (TElPaperQu q : batchQuList
        ) {
//            executorService.execute(() -> {
//                try {
                    tElPaperQuMapper.insertTElPaperQu(q);
//                }finally {
//                    latch.countDown(); //线程计数
//                }
//            });
        }
//        try {
//            latch.await(); //线程计数完毕后继续执行
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//        executorService.shutdown();


        //批量添加问题答案
        //线程池
        ExecutorService executorService2 = Executors.newFixedThreadPool(30);
        final CountDownLatch latch2 = new CountDownLatch(batchAnswerList.size()); //相同线程数量的计数
        for (TElPaperQuAnswer answer : batchAnswerList
        ) {
            executorService2.execute(() -> {
                try {
                    tElPaperQuAnswerMapper.insertTElPaperQuAnswer(answer);
                }finally {
                    latch2.countDown(); //线程计数
                }
            });
        }
        try {
            latch2.await(); //线程计数完毕后继续执行
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        executorService2.shutdown();

    }

    /**
     * 填充试题题目信息
     *
     * @param repo
     * @param qu
     * @return
     */
    private TElPaperQu processPaperQu(TElExamRepo repo, TElQu qu) {

        //保存试题信息
        TElPaperQu paperQu = new TElPaperQu();
        paperQu.setQuId(qu.getQuId());
        paperQu.setAnswered(0l);
        paperQu.setIsRight(0l);
        paperQu.setQuType(qu.getQuType());

        if ("1".equals(qu.getQuType().toString())) {
            paperQu.setScore(repo.getRadioScore());
            paperQu.setActualScore(repo.getRadioScore());
        }

        if ("2".equals(qu.getQuType().toString())) {
            paperQu.setScore(repo.getMultiScore());
            paperQu.setActualScore(repo.getMultiScore());
        }

        if ("3".equals(qu.getQuType().toString())) {
            paperQu.setScore(repo.getJudgeScore());
            paperQu.setActualScore(repo.getJudgeScore());
        }

        return paperQu;
    }

    /**
     * 准确的时间点到表达式
     *
     * @param date
     * @return
     */
    public static String dateToCron(final Date date) {
        SimpleDateFormat fmt = new SimpleDateFormat("ss mm HH dd MM ? yyyy");
        String formatTimeStr = "";
        if (date != null) {
            formatTimeStr = fmt.format(date);
        }
        return formatTimeStr;
    }
}
