package com.sundot.airport.exam.common.manager.impl;

import cn.hutool.core.bean.BeanUtil;
import com.sundot.airport.common.utils.SecurityUtils;
import com.sundot.airport.exam.common.CheckUtil;
import com.sundot.airport.exam.common.manager.ExamRecordManager;
import com.sundot.airport.exam.common.model.params.GetExamRecordParam;
import com.sundot.airport.exam.common.model.result.GetExamRecordResult;
import com.sundot.airport.exam.common.model.result.sub.ExamRecordOption;
import com.sundot.airport.exam.common.model.result.sub.ExamRecordQuestion;
import com.sundot.airport.exam.common.service.ExamRecOptService;
import com.sundot.airport.exam.common.service.ExamRecService;
import com.sundot.airport.exam.domain.ExamRec;
import com.sundot.airport.exam.domain.ExamRecOpt;
import com.sundot.airport.exam.domain.Ques;
import com.sundot.airport.exam.enums.CloudSchoolBizExceptionEnum;
import com.sundot.airport.exam.enums.CorrectStatusEnum;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <b>功能名：ExamRecordManagerImpl</b><br>
 * <b>说明：</b> 测试记录通用业务处理实现层 <br>
 * <b>著作权：</b> Copyright (C) 2021 HUIFANEDU  CORPORATION<br>
 * <b>修改履历：</b><br>
 *
 * @author 2021-07-06 Mokou
 */
@Service
public class ExamRecordManagerImpl implements ExamRecordManager {

    @Resource
    private ExamRecService examRecService;
    @Resource
    private ExamRecOptService examRecOptService;

    @Override
    public GetExamRecordResult getExamRecord(GetExamRecordParam param) {
        String uid = SecurityUtils.getUserId().toString();
        //ThreadContext.get().getUsrId();

        // 查询测试记录表
        Optional<ExamRec> examRecOpt = examRecService.getByIdAndUserId(param.getErId(), uid);
        CheckUtil.boolCheck(!examRecOpt.isPresent(), CloudSchoolBizExceptionEnum.EXAMREC_NOT_FOUND);

        GetExamRecordResult examRecordRes = new GetExamRecordResult();
        BeanUtil.copyProperties(examRecOpt.get(), examRecordRes);

        // 用户作答选项 已排序
        List<ExamRecOpt> examRecOptList = examRecOptService.byErId(examRecOpt.get().getErId());

        // 初始容量(不精确)
        int mapInitCap = (int) (examRecOptList.size() / 0.75) + 1;

        // 保存题目id与题目的映射关系 减少遍历次数
        Map<String, Ques> quesIdQuesMap = new HashMap<>(mapInitCap);
        // 初始化题目id与选项列表的映射关系 减少遍历次数
        Map<String, List<ExamRecOpt>> quesIdQuesOptMap = new HashMap<>(mapInitCap);
        // 初始化题目id与选项列表的映射关系 减少遍历次数
        Map<String, String> quesIdQcNameMap = new HashMap<>(mapInitCap);
        // 初始化题目id与排序号映射关系 减少遍历次数
        Map<String, Integer> quesIdQuSortMap = new HashMap<>(mapInitCap);
        // 去重后的题目ID
        List<String> quIds = new ArrayList<>();

        for (ExamRecOpt item : examRecOptList) {
            if (quesIdQuesMap.get(item.getEroQuId()) == null) {
                // 保存题干内容
                Ques ques = new Ques();
                ques.setQuContent(item.getEroQuContent());
                ques.setQuType(item.getEroQuType());
                quesIdQuesMap.put(item.getEroQuId(), ques);
            }

            // 初始化选项列表
            quesIdQuesOptMap.computeIfAbsent(item.getEroQuId(), k -> new ArrayList<>());
            // 保存用户答题选项
            quesIdQuesOptMap.get(item.getEroQuId()).add(item);
            // 保存题目分类名
            quesIdQcNameMap.computeIfAbsent(item.getEroQuId(), k -> item.getEroQcName());
            // 保存题目排序号
            quesIdQuSortMap.computeIfAbsent(item.getEroQuId(), k -> item.getEroTpqSort());
            // 保存去重后的题目ID
            if (!quIds.contains(item.getEroQuId())) {
                quIds.add(item.getEroQuId());
            }
        }

        // 通过遍历已排好序的题目ID列表 按顺序写入对应的结果
        List<ExamRecordQuestion> resQuestionList = new ArrayList<>();

        for (String quId : quIds) {
            // 题目对象
            Ques queryQues = quesIdQuesMap.get(quId);
            if (queryQues == null) {
                continue;
            }

            List<ExamRecOpt> optList = quesIdQuesOptMap.get(quId);

            // 写入需要返回的题目数据
            ExamRecordQuestion resQues = new ExamRecordQuestion();
            resQues.setEroQuContent(queryQues.getQuContent());
            resQues.setEroQuType(queryQues.getQuType());
            if (optList != null && optList.size() > 0) {
                resQues.setEroTpqTotalScore(optList.get(0).getEroTpqTotalScore());
                resQues.setEroTpqCompType(optList.get(0).getEroTpqCompType());
                resQues.setEroTpqLeftScore(optList.get(0).getEroTpqLeftScore());
                resQues.setEroTpqRightScore(optList.get(0).getEroTpqRightScore());

                resQues.setOption(optList.stream().map(item -> new ExamRecordOption() {
                    {
                        BeanUtil.copyProperties(item, this);
                    }
                }).collect(Collectors.toList()));
            }
            resQues.setEroTpqSort(quesIdQuSortMap.get(quId));
            resQues.setEroQcName(quesIdQcNameMap.get(quId));
            resQuestionList.add(resQues);
        }

        examRecordRes.setQuestion(resQuestionList);

        return examRecordRes;
    }

    @Override
    public CorrectStatusEnum getCorrectStatusByOpts(List<ExamRecordOption> optionList) {
        if (optionList == null || optionList.size() == 0) {
            return CorrectStatusEnum.NOT_FILLED;
        }

        for (ExamRecordOption opt : optionList) {
            if (!opt.getEroCorrectStatus().equals(CorrectStatusEnum.NONE)) {
                return opt.getEroCorrectStatus();
            }
        }

        return CorrectStatusEnum.NOT_FILLED;
    }
}
