package com.qmth.themis.business.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qmth.themis.business.cache.ExamRecordCacheUtil;
import com.qmth.themis.business.cache.ExamingDataCacheUtil;
import com.qmth.themis.business.cache.RedisKeyHelper;
import com.qmth.themis.business.constant.SystemConstant;
import com.qmth.themis.business.dto.MqDto;
import com.qmth.themis.business.entity.TOeExamBreakHistory;
import com.qmth.themis.business.entity.TOeExamRecord;
import com.qmth.themis.business.enums.ExamRecordStatusEnum;
import com.qmth.themis.business.enums.MqTagEnum;
import com.qmth.themis.business.service.CommonService;
import com.qmth.themis.business.service.MqDtoService;
import com.qmth.themis.business.service.TOeExamBreakHistoryService;
import com.qmth.themis.business.service.TOeExamRecordService;
import com.qmth.themis.business.util.MqUtil;
import com.qmth.themis.business.util.RedisUtil;
import com.qmth.themis.business.util.TencentYunUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @Description:
 * @Author: xiatian
 * @Date: 2020-08-04
 */
@Service
public class CommonServiceImpl implements CommonService {
    private final static Logger log = LoggerFactory.getLogger(CommonService.class);

    @Resource
    TOeExamRecordService examRecordService;

    @Resource
    RedisUtil redisUtil;

    @Resource
    MqDtoService mqDtoService;

    @Resource
    MqUtil mqUtil;

    @Resource
    TOeExamBreakHistoryService tOeExamBreakHistoryService;

    @Resource
    TencentYunUtil tencentYunUtil;

    /**
     * 考试记录数据持久化
     *
     * @param recordId
     * @param studentId
     */
    @Override
    public void persisted(Long recordId, Long studentId) {
        String lockKey = SystemConstant.REDIS_LOCK_EXAM_RECORD_PERSISTED_PREFIX + recordId;
        Boolean lock = redisUtil.lock(lockKey, SystemConstant.REDIS_CACHE_TIME_OUT);
        if (!lock) {
            log.info("persisted doing,request ignore recordId:" + recordId);
            return;
        }

        try {
            ExamRecordStatusEnum status = ExamRecordCacheUtil.getStatus(recordId);
            Double score = ExamRecordCacheUtil.getObjectiveScore(recordId);
            if (Objects.isNull(status) || Objects.isNull(score)) {
                TOeExamRecord tOeExamRecord = SystemConstant.getExamRecord(recordId);
                status = tOeExamRecord.getStatus();
                score = tOeExamRecord.getObjectiveScore();
            }
            if (Objects.isNull(status) || !ExamRecordStatusEnum.FINISHED.equals(status)) {
                log.info("status error ,status:" + status + " recordId:" + recordId);
                return;
            }
            if (Objects.isNull(score)) {
                log.info("score is null ,recordId:" + recordId);
                //算分未完成的 发送10秒延迟消息
                Map<String, Object> propMap = mqDtoService.buildMqDelayMsg("10s");
                propMap.put(SystemConstant.RECORD_ID, recordId);
                propMap.put(SystemConstant.STUDENT_ID, studentId);
                MqDto mqDto = new MqDto(mqUtil.getTopic(), MqTagEnum.EXAM_RECORD_PERSISTED.name(),
                        propMap, MqTagEnum.EXAM_RECORD_PERSISTED, recordId.toString(), propMap, recordId.toString());
                mqDtoService.assembleSendAsyncDelayMsg(mqDto);
                return;
            }
            log.info("start persisted,recordId:" + recordId);
            examRecordService.saveDataByCache(recordId);
            this.deleteExamStudentCache(recordId, studentId);
            log.info("end persisted,recordId:" + recordId);
        } finally {
            redisUtil.releaseLock(lockKey);
        }
    }

    /**
     * 删除考生缓存
     *
     * @param recordId
     * @param studentId
     */
    @Override
    public void deleteExamStudentCache(Long recordId, Long studentId) {
        try {
            //判断当前结束的考试记录ID是否是未完成的考试记录ID
            if (Objects.equals(recordId, ExamingDataCacheUtil.getUnFinishedRecordId(studentId))) {
                ExamingDataCacheUtil.deleteUnFinishedRecordId(studentId);
            }
            if (Objects.equals(recordId, ExamingDataCacheUtil.getExamingRecordId(studentId))) {
                ExamingDataCacheUtil.deleteExamingRecordId(studentId);
            }

            redisUtil.delete(RedisKeyHelper.examRecordCacheKey(recordId));
            redisUtil.delete(RedisKeyHelper.examAnswerKey(recordId));
            redisUtil.delete(RedisKeyHelper.audioLeftPlayCountKey(recordId));
            redisUtil.delete(RedisKeyHelper.livenessVerifyCacheKey(recordId));
            redisUtil.delete(RedisKeyHelper.faceVerifyCacheKey(recordId));
            //2021-03-01新增
            redisUtil.delete(RedisKeyHelper.studentPaperStructKey(recordId));
            //先查询之前的断点记录
            QueryWrapper<TOeExamBreakHistory> tOeExamBreakHistoryQueryWrapper = new QueryWrapper<>();
            tOeExamBreakHistoryQueryWrapper.lambda().eq(TOeExamBreakHistory::getExamRecordId, recordId);
            List<TOeExamBreakHistory> tOeExamBreakHistoryList = tOeExamBreakHistoryService.list(tOeExamBreakHistoryQueryWrapper);
            //删除历史断点缓存
            if (Objects.nonNull(tOeExamBreakHistoryList) && tOeExamBreakHistoryList.size() > 0) {
                tOeExamBreakHistoryList.forEach(s -> {
                    redisUtil.delete(RedisKeyHelper.examBreakCacheKey(s.getId()));
                });
            }
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
        }
    }

    /**
     * 解散房间
     *
     * @param recordId
     */
    @Override
    public void dismissRoomByStrRoomId(Long recordId) {
        try {
            tencentYunUtil.dismissRoomByStrRoomId(tencentYunUtil.getSecretId(),
                    tencentYunUtil.getSecretKey(),
                    tencentYunUtil.getTrtcQueryUrl(),
                    tencentYunUtil.getTrtcRegion(),
                    Long.parseLong(tencentYunUtil.getAppId()),
                    String.valueOf(recordId));
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
        }
    }
}
