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

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qmth.themis.business.cache.ExamRecordCacheUtil;
import com.qmth.themis.business.cache.bean.ExamStudentCacheBean;
import com.qmth.themis.business.dto.WarningDto;
import com.qmth.themis.business.entity.TEConfig;
import com.qmth.themis.business.entity.TEExamStudentLog;
import com.qmth.themis.business.entity.TIeInvigilateWarnInfo;
import com.qmth.themis.business.entity.TOeFaceVerifyHistory;
import com.qmth.themis.business.enums.ExamTypeEnum;
import com.qmth.themis.business.enums.VerifyExceptionEnum;
import com.qmth.themis.business.enums.WarningLevelEnum;
import com.qmth.themis.business.service.*;
import com.qmth.themis.business.util.RedisUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * @Description: 预警规则公用
 * @Param:
 * @return:
 * @Author: wangliang
 * @Date: 2020/8/18
 */
@Service
public class WarningServiceImpl implements WarningService {
    private final static Logger log = LoggerFactory.getLogger(WarningServiceImpl.class);

    @Resource
    TEConfigService teConfigService;

    @Resource
    TOeFaceVerifyHistoryService faceVerifyHistoryService;

    @Resource
    TIeInvigilateWarnInfoService tIeInvigilateWarnInfoService;

    @Resource
    TEExamStudentLogService teExamStudentLogService;

    @Resource
    TEExamStudentService teExamStudentService;

    /**
     * 人脸数量异常
     *
     * @param warningDto
     */
    @Override
    @Transactional
    public void faceCountError(WarningDto warningDto) {
        Long recordId = warningDto.getRecordId();
        Integer faceCount = warningDto.getFaceCount();
        VerifyExceptionEnum warningEnum = warningDto.getWarningEnum();
        String photoUrl = warningDto.getPhotoUrl();
        TEConfig teConfig = teConfigService.getGlobalConfig();
        Long examId = ExamRecordCacheUtil.getExamId(recordId);
        Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
        Long examActivityId = ExamRecordCacheUtil.getExamActivityId(recordId);
        ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(examStudentId);
        if (faceCount > 1) {//多张人脸
            Map<String, Object> map = faceVerifyHistoryService.faceCountError(recordId, warningDto.getWarningEnum().name(), faceCount, true, ExamTypeEnum.IN_PROCESS.name(), warningDto.getRandom());
            if (Objects.nonNull(map) && map.size() > 0) {
                Integer count = Integer.parseInt(String.valueOf(map.get("tmpCount")));
                count = Objects.isNull(count) ? 0 : count;
                if (count >= teConfig.getMultipleFaceCountError()) {
                    TIeInvigilateWarnInfo tIeInvigilateWarnInfo = new TIeInvigilateWarnInfo(examId, examActivityId, recordId, examStudentId, warningEnum.getLevel().get(1), WarningLevelEnum.valueOf(warningEnum.getLevel().get(1)).getDesc(), warningEnum, photoUrl);
                    tIeInvigilateWarnInfoService.saveOrUpdate(tIeInvigilateWarnInfo);
                    this.setWarningCount(recordId);
                    this.setPhotoUrls(map, photoUrl, tIeInvigilateWarnInfo, examStudentCacheBean, recordId);
                }
            }
        } else if (faceCount <= 0) {//未检测到人脸
            Map<String, Object> map = faceVerifyHistoryService.faceCountError(recordId, warningDto.getWarningEnum().name(), faceCount, false, ExamTypeEnum.IN_PROCESS.name(), warningDto.getRandom());
            if (Objects.nonNull(map) && map.size() > 0) {
                Integer count = Integer.parseInt(String.valueOf(map.get("tmpCount")));
                count = Objects.isNull(count) ? 0 : count;
                if (count >= teConfig.getNoFaceCountError()) {
                    TIeInvigilateWarnInfo tIeInvigilateWarnInfo = new TIeInvigilateWarnInfo(examId, examActivityId, recordId, examStudentId, warningEnum.getLevel().get(0), WarningLevelEnum.valueOf(warningEnum.getLevel().get(0)).getDesc(), warningEnum, photoUrl);
                    tIeInvigilateWarnInfoService.saveOrUpdate(tIeInvigilateWarnInfo);
                    this.setWarningCount(recordId);
                    this.setPhotoUrls(map, photoUrl, tIeInvigilateWarnInfo, examStudentCacheBean, recordId);
                }
            }
        }
    }

    /**
     * 人脸比对异常
     *
     * @param warningDto
     */
    @Override
    @Transactional
    public void faceCompareError(WarningDto warningDto) {
        Long recordId = warningDto.getRecordId();
        VerifyExceptionEnum warningEnum = warningDto.getWarningEnum();
        String photoUrl = warningDto.getPhotoUrl();
        TEConfig teConfig = teConfigService.getGlobalConfig();
        Long examId = ExamRecordCacheUtil.getExamId(recordId);
        Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
        Long examActivityId = ExamRecordCacheUtil.getExamActivityId(recordId);
        ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(examStudentId);
        Map<String, Object> map = faceVerifyHistoryService.faceCompareError(recordId, warningDto.getWarningEnum().name(), ExamTypeEnum.IN_PROCESS.name(), warningDto.getRandom());
        if (Objects.nonNull(map) && map.size() > 0) {
            Integer count = Integer.parseInt(String.valueOf(map.get("tmpCount")));
            count = Objects.isNull(count) ? 0 : count;
            if (count >= teConfig.getMatchFaceCompareErrorCount()) {
                TIeInvigilateWarnInfo tIeInvigilateWarnInfo = new TIeInvigilateWarnInfo(examId, examActivityId, recordId, examStudentId, warningEnum.getLevel().get(0), WarningLevelEnum.valueOf(warningEnum.getLevel().get(0)).getDesc(), warningEnum, photoUrl);
                tIeInvigilateWarnInfoService.saveOrUpdate(tIeInvigilateWarnInfo);
                this.setWarningCount(recordId);
                this.setPhotoUrls(map, photoUrl, tIeInvigilateWarnInfo, examStudentCacheBean, recordId);
            }
            if (count >= teConfig.getTotalFaceCompareErrorCount()) {
                TIeInvigilateWarnInfo tIeInvigilateWarnInfo = new TIeInvigilateWarnInfo(examId, examActivityId, recordId, examStudentId, warningEnum.getLevel().get(1), WarningLevelEnum.valueOf(warningEnum.getLevel().get(1)).getDesc(), warningEnum, photoUrl);
                tIeInvigilateWarnInfoService.saveOrUpdate(tIeInvigilateWarnInfo);
                this.setWarningCount(recordId);
                this.setPhotoUrls(map, photoUrl, tIeInvigilateWarnInfo, examStudentCacheBean, recordId);
            }
        }
    }

    /**
     * 闭眼检测异常
     *
     * @param warningDto
     */
    @Override
    public void eyeCloseError(WarningDto warningDto) {

    }

    /**
     * 活体动作异常
     *
     * @param warningDto
     */
    @Override
    public void livenessActionError(WarningDto warningDto) {

    }

    /**
     * 真实性异常
     *
     * @param warningDto
     */
    @Override
    @Transactional
    public void realnessError(WarningDto warningDto) {
        Long recordId = warningDto.getRecordId();
        VerifyExceptionEnum warningEnum = warningDto.getWarningEnum();
        TEConfig teConfig = teConfigService.getGlobalConfig();
        Long examId = ExamRecordCacheUtil.getExamId(recordId);
        Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
        Long examActivityId = ExamRecordCacheUtil.getExamActivityId(recordId);
        QueryWrapper<TOeFaceVerifyHistory> tOeFaceVerifyHistoryQueryWrapper = new QueryWrapper<>();
        tOeFaceVerifyHistoryQueryWrapper.lambda().eq(TOeFaceVerifyHistory::getExamRecordId, recordId).eq(TOeFaceVerifyHistory::getException, warningEnum.name());
        ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(examStudentId);
        int count = faceVerifyHistoryService.count(tOeFaceVerifyHistoryQueryWrapper);
        if (count > teConfig.getRealnessCount()) {
            TIeInvigilateWarnInfo tIeInvigilateWarnInfo = new TIeInvigilateWarnInfo(examId, examActivityId, recordId, examStudentId, WarningLevelEnum.D15.name(), WarningLevelEnum.D15.getDesc(), warningEnum);
            tIeInvigilateWarnInfoService.saveOrUpdate(tIeInvigilateWarnInfo);
            this.setWarningCount(recordId);
            TEExamStudentLog teExamStudentLog = new TEExamStudentLog(tIeInvigilateWarnInfo.getType().name(), tIeInvigilateWarnInfo.getType().getCode(), tIeInvigilateWarnInfo.getType().getCode(), examStudentCacheBean.getStudentId(), examStudentCacheBean.getId(), recordId);
            teExamStudentLogService.saveOrUpdate(teExamStudentLog);
        }
    }

    /**
     * 设置预警数
     *
     * @param recordId
     */
    public void setWarningCount(Long recordId) {
        Integer warningCount = ExamRecordCacheUtil.getWarningCount(recordId);
        if (Objects.nonNull(warningCount)) {
            warningCount++;
            ExamRecordCacheUtil.setWarningCount(recordId, warningCount, true);
        } else {
            ExamRecordCacheUtil.setWarningCount(recordId, 1, true);
        }
    }

    /**
     * 设置图片集合
     *
     * @param map
     * @param photoUrl
     * @param tIeInvigilateWarnInfo
     * @param examStudentCacheBean
     * @param recordId
     */
    public void setPhotoUrls(Map<String, Object> map, String photoUrl, TIeInvigilateWarnInfo tIeInvigilateWarnInfo, ExamStudentCacheBean examStudentCacheBean, Long recordId) {
        List<String> photoUrls = new ArrayList();
        if (Objects.nonNull(map.get("photoUrls")) && !Objects.equals(map.get("photoUrls"), "")) {
            String[] s = String.valueOf(map.get("photoUrls")).split(",");
            Collections.addAll(photoUrls, s);
        }
        photoUrls.add(photoUrl);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("PHOTOS", photoUrls);
        jsonObject.put("MIN_CREATE_TIME", map.get("createTime"));
        TEExamStudentLog teExamStudentLog = new TEExamStudentLog(tIeInvigilateWarnInfo.getType().name(), tIeInvigilateWarnInfo.getType().getCode(), jsonObject.toJSONString(), examStudentCacheBean.getStudentId(), examStudentCacheBean.getId(), recordId);
        teExamStudentLogService.saveOrUpdate(teExamStudentLog);
    }
}
