package com.zd.exam.service.impl;

import java.util.*;
import java.util.stream.Collectors;

import com.zd.common.core.exception.ServiceException;
import com.zd.common.core.utils.DateUtils;
import com.zd.common.core.utils.SecurityUtils;
import com.zd.common.core.utils.StringUtils;
import com.zd.common.security.service.TokenService;
import com.zd.common.security.utils.SaveUtil;

import com.zd.exam.domain.*;
import com.zd.exam.enums.ConvertType;
import com.zd.exam.enums.QuType;
import com.zd.exam.mapper.*;
import com.zd.exam.service.ElQuAnswerService;
import com.zd.exam.service.IElConvertRecordService;
import com.zd.exam.service.convert.BonusPointsService;
import com.zd.exam.service.convert.ConvertTimingService;
import com.zd.exam.service.convert.LabBlackConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.zd.exam.service.IElPractiseService;
import org.springframework.util.CollectionUtils;

/**
 * 练习记录Service业务层处理
 *
 * @author liubo
 * @date 2021-12-14
 */
@Service
public class ElPractiseServiceImpl implements IElPractiseService {
    @Autowired
    private ElPractiseMapper elPractiseMapper;
    @Autowired
    private ElQuMapper quMapper;
    @Autowired
    private ElQuAnswerService elQuAnswerService;
    @Autowired
    private ElPractiseQuMapper practiseQuMapper;
    @Autowired
    private ElPractiseQuAnswerMapper practiseQuAnswerMapper;
    @Autowired
    private IElConvertRecordService convertRecordService;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private BonusPointsService bonusPointsService;
    @Autowired
    private ConvertTimingService convertTimingService;

    /**
     * 查询练习记录
     *
     * @param id 练习记录主键
     * @return 练习记录
     */
    @Override
    public ElPractise selectElPractiseById(Long id) {

        // 试题基本信息
        ElPractise practise = elPractiseMapper.selectElPractiseById(id);
        if (practise == null) {
            throw new ServiceException("未查询到练习，ID无效");
        }

        // 查找题目列表
        ElPractiseQu elPractiseQu = new ElPractiseQu();
        elPractiseQu.setPractiseId(practise.getId());
        List<ElPractiseQu> list = practiseQuMapper.selectElPractiseQuList(elPractiseQu);

        List<ElPractiseQu> radioList = new ArrayList<>();
        List<ElPractiseQu> multiList = new ArrayList<>();
        List<ElPractiseQu> judgeList = new ArrayList<>();
        for (ElPractiseQu item : list) {
            if (QuType.RADIO.equals(item.getQuType())) {
                radioList.add(item);
            }
            if (QuType.MULTI.equals(item.getQuType())) {
                multiList.add(item);
            }
            if (QuType.JUDGE.equals(item.getQuType())) {
                judgeList.add(item);
            }
        }

        practise.setRadioList(radioList);
        practise.setMultiList(multiList);
        practise.setJudgeList(judgeList);
        return practise;

    }

    /**
     * 查询练习记录列表
     *
     * @param elPractise 练习记录
     * @return 练习记录
     */
    @Override
    public List<ElPractise> selectElPractiseList(ElPractise elPractise) {
        return elPractiseMapper.selectElPractiseList(elPractise);
    }

    /**
     * 新增练习记录
     *
     * @param elPractise 练习记录
     * @return 结果
     */
    @Override
    public ElPractise insertElPractise(ElPractise elPractise) {
        //设置其他公共字段
        SaveUtil.setCommonAttr(elPractise);
        elPractise.setJoinUserId(tokenService.getLoginUser().getUserid());
        int num = elPractiseMapper.insertElPractise(elPractise);
        if(num == 0){
            throw new ServiceException("添加失败！");
        }
        return elPractise;
    }

    /**
     * 修改练习记录
     *
     * @param elPractise 练习记录
     * @return 结果
     */
    @Override
    public int updateElPractise(ElPractise elPractise) {
        elPractise.setUpdateTime(DateUtils.getNowDate());
        elPractise.setUpdateBy(SecurityUtils.getUsername());
        return elPractiseMapper.updateElPractise(elPractise);
    }

    /**
     * 批量删除练习记录
     *
     * @param ids 需要删除的练习记录主键
     * @return 结果
     */
    @Override
    public int deleteElPractiseByIds(Long[] ids) {
        return elPractiseMapper.deleteElPractiseByIds(ids);
    }

    /**
     * 删除练习记录信息
     *
     * @param id 练习记录主键
     * @return 结果
     */
    @Override
    public int deleteElPractiseById(Long id) {
        return elPractiseMapper.deleteElPractiseById(id);
    }

    /**
     * 选择题目类型，开始练习
     */
    @Override
    public Long createPractise(String classifyIds) {
        ElPractise elPractise = new ElPractise();
        elPractise.setClassifyIds(classifyIds);

        List<Long> cIds = Arrays.asList(classifyIds .split(",")).stream().map(s -> (Long.parseLong(s.trim()))).collect(Collectors.toList());

        // 创建练习默认给200 道题，如果用户处于黑名单，则取黑名单配置的数量

        int quNum = 200;
        LabBlackConfig blackConfig = bonusPointsService.getBlackTimeArea(SecurityUtils.getUserId());
        if(blackConfig != null && blackConfig.getNumberTopics() != null && blackConfig.getNumberTopics() > 0){
            quNum = Math.toIntExact(blackConfig.getNumberTopics());
        }

        List<ElQu> quList = quMapper.queryByIds(null, cIds, quNum);
        if(org.apache.commons.collections4.CollectionUtils.isEmpty(quList)){
            throw new ServiceException("练习失败，未找到对应的题目！");
        }


        List<ElPractiseQu> practiseQuList = new ArrayList<>();
        ElPractiseQu practiseQu = new ElPractiseQu();
        for (ElQu qu : quList) {
            //保存试题信息
            practiseQu = new ElPractiseQu();
            practiseQu.setQuId(qu.getId());
            practiseQu.setAnswered(0);
            practiseQu.setIsRight(0);
            practiseQu.setQuType(qu.getQuType());

            practiseQu.setScore(0);
            practiseQu.setActualScore(0);

            practiseQuList.add(practiseQu);
        }

        insertElPractise(elPractise);

        savePractiseQu(elPractise.getId(), practiseQuList);

        return elPractise.getId();
    }

    /**
     * 练习保存答案
     * @param practiseQu
     */
    @Override
    public void fillPractiseAnswer(ElPractiseQu practiseQu) {
        // 选择哪个答案，list 中提交哪个ID
        List<ElPractiseQuAnswer> practiseQuAnswerList = practiseQu.getAnswerList();
        if (CollectionUtils.isEmpty(practiseQuAnswerList)
                && StringUtils.isBlank(practiseQu.getAnswer())) {
            // 未作答
            return;
        }

        practiseQu = practiseQuMapper.selectOneElPractiseQu(practiseQu);
        if (practiseQu == null) {
            throw new ServiceException("参数无效！");
        }
        //查找答案列表
        ElPractiseQuAnswer elPractiseQuAnswer = new ElPractiseQuAnswer();
        elPractiseQuAnswer.setPractiseId(practiseQu.getPractiseId());
        elPractiseQuAnswer.setQuId(practiseQu.getQuId());
        List<ElPractiseQuAnswer> list = practiseQuAnswerMapper.selectElPractiseQuAnswerList(elPractiseQuAnswer);

        //是否正确
        boolean right = true;

        //更新正确答案
        for (ElPractiseQuAnswer item : list) {

            // 保存答案，先初始化，防止多选题重复修改，选项不一致情况
            item.setChecked(0);
            for (ElPractiseQuAnswer elPaperQuAnswer : practiseQuAnswerList) {
                if (elPaperQuAnswer.getId().equals(item.getId())) {
                    item.setChecked(1);
                    break;
                }
            }

            //有一个对不上就是错的
            if (item.getIsRight() != null && !item.getIsRight().equals(item.getChecked())) {
                right = false;
            }
            practiseQuAnswerMapper.updateElPractiseQuAnswer(item);
        }

        //修改为已回答
        practiseQu.setIsRight(right ? 1 : 0);
        // practiseQu.setAnswer(practiseQu.getAnswer());
        practiseQu.setAnswered(1);

        practiseQuMapper.updateElPractiseQu(practiseQu);
    }

    /**
     * 模拟练习 提交数据统计
     */
    @Override
    public Map<String, Object> handPractise(ElPractise practise) {

        practise = elPractiseMapper.selectElPractiseById(practise.getId());
        if(practise == null){
            throw new ServiceException("ID 无效");
        }
        Map<String, Object> map = practiseQuMapper.selectCountByPractiseId(practise.getId());

        // 完成添加换算记录
        Long convertRecordId = null;
        if((Long) map.get("correctly") > 0){
            ElConvertRecord elConvertRecord = new ElConvertRecord();
            elConvertRecord.setType(ConvertType.PRACTISE);
            // 此处业务ID 为练习ID
            elConvertRecord.setBusinessId(practise.getId());
            elConvertRecord.setBusinessNum((Long) map.get("correctly"));
            elConvertRecord.setStatus(0);
            elConvertRecord.setUseNum(0L);

            convertRecordService.insertElConvertRecord(elConvertRecord);
            convertRecordId = elConvertRecord.getId();

        }


        // 通过elConvertRecord 换算记录直接执行获取换算结果返回数值
        // 获得奖励积分
        map.put("points", convertRecordId != null ? convertTimingService.doConvertById(convertRecordId) : 0);

        //  练习结束 恢复黑名单
        Map<String, Object> data = new HashMap<>();
        data.put("practiceStatus", 0);
        data.put("numberTopics", Integer.parseInt(map.get("unAnswered")+"") + Integer.parseInt(map.get("answered")+""));
        data.put("numberAccuracy", map.get("accuracy"));
        bonusPointsService.blackCallback(practise.getJoinUserId(), data, 2);

        return map;
    }

    private void savePractiseQu(Long practiseId, List<ElPractiseQu> practiseQuList) {

        List<ElPractiseQu> batchQuList = new ArrayList<>();
        List<ElPractiseQuAnswer> batchAnswerList = new ArrayList<>();

        int sort = 0;
        for (ElPractiseQu item : practiseQuList) {

            item.setPractiseId(practiseId);
            item.setSort(sort);

            //回答列表
            List<ElQuAnswer> answerList = elQuAnswerService.queryByQuId(item.getQuId());

            if (!CollectionUtils.isEmpty(answerList)) {

                int ii = 0;
                for (ElQuAnswer answer : answerList) {
                    ElPractiseQuAnswer quAnswer = new ElPractiseQuAnswer();
                    quAnswer.setPractiseId(practiseId);
                    quAnswer.setQuId(answer.getQuId());
                    quAnswer.setAnswerId(answer.getId());
                    quAnswer.setChecked(0);
                    quAnswer.setSort(ii);
                    quAnswer.setAbc(QuType.ABC.get(ii));
                    quAnswer.setIsRight(answer.getIsRight());
                    ii++;
                    batchAnswerList.add(quAnswer);
                }
            }

            batchQuList.add(item);
            sort++;
        }

        //添加问题
        practiseQuMapper.insertBatchPractiseQu(batchQuList);

        //批量添加问题答案
        practiseQuAnswerMapper.insertBatchPractiseQuAnswer(batchAnswerList);
    }
}
