package com.qmth.themis.business.service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.qmth.themis.business.bean.admin.*;
import com.qmth.themis.business.cache.bean.ExamRecordDetailBean;
import com.qmth.themis.business.cache.bean.ExamRecordPaperViewBean;
import com.qmth.themis.business.dto.response.MarkResultDto;
import com.qmth.themis.business.entity.TIeInvigilateWarnInfo;
import com.qmth.themis.business.entity.TOeExamRecord;
import com.qmth.themis.business.enums.*;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @Description: 考试记录 服务类
 * @Param:
 * @return:
 * @Author: wangliang
 * @Date: 2020/6/25
 */
public interface TOeExamRecordService extends IService<TOeExamRecord> {

    TOeExamRecord saveByPrepare(Long examId, Long examActivityId, Long examStudentId, Long paperId, Integer serialNumber, Long studentId, Integer mobilePhotoUpload);

    /**
     * 计算客观分
     *
     * @param param
     */
//    void calculateObjectiveScore(Map<String, Object> param);

    /**
     * 考试记录数据持久化
     *
     * @param recordId
     */
    public void saveDataByCache(Long recordId);

    void saveFaceVerify(ExamTypeEnum type, Long recordId, Long entryAuthenticationId,
                        VerifyExceptionEnum entryAuthenticationResult);

    void saveLivenessVerify(LivenessTypeEnum type, Long recordId, Long entryAuthenticationId,
                            VerifyExceptionEnum entryAuthenticationResult);

    /**
     * 保存考试记录数据
     *
     * @param recordId
     */
    void examRecordDataSave(Long recordId);

    /**
     * 发送mq更新考试记录
     *
     * @param recordId
     * @param timestamp
     */
    void sendExamRecordDataSaveMq(Long recordId, Long timestamp);

    /**
     * 发送mq更新考试预警数量记录
     *
     * @param recordId
     */
    void sendExamRecordDataUpdateWarningCountMq(Long recordId);

    /**
     * 发送mq更新考试预警未读数量
     *
     * @param recordId
     * @param number
     */
    void sendExamRecordDataUpdateWarningUnreadMq(Long recordId, Integer number);

    /**
     * 发送mq更新考试记录
     *
     * @param recordId
     * @param timestamp
     */
    void sendExamRecordDataSaveMqNotIp(Long recordId, Long timestamp);

    /**
     * 查询实时监控台视频列表
     *
     * @param iPage
     * @param examId
     * @param examActivityId
     * @param roomCode
     * @param paperDownload
     * @param status
     * @param name
     * @param identity
     * @param minWarningCount
     * @param maxWarningCount
     * @param clientWebsocketStatus
     * @param cameraMonitorStatus
     * @param screenMonitorStatus
     * @param mobileFirstMonitorStatus
     * @param mobileSecondMonitorStatus
     * @param userId
     * @param orgId
     * @return
     */
    public IPage<InvigilateListVideoBean> invigilatePageListVideo(IPage<Map> iPage, Long examId,
                                                                  Long examActivityId,
                                                                  String roomCode,
                                                                  Integer paperDownload,
                                                                  String status,
                                                                  String name,
                                                                  String identity,
                                                                  Integer minWarningCount,
                                                                  Integer maxWarningCount,
                                                                  String clientWebsocketStatus,
                                                                  String cameraMonitorStatus,
                                                                  String screenMonitorStatus,
                                                                  String mobileFirstMonitorStatus,
                                                                  String mobileSecondMonitorStatus,
                                                                  Long userId,
                                                                  Long orgId);

    /**
     * 实时监控台视频随机列表
     *
     * @param examId
     * @param userId
     * @param randomNum
     * @param orgId
     * @return
     */
    public List<InvigilateListVideoBean> invigilatePageListVideoRandom(Long examId, Long userId, Integer randomNum, Long orgId);

    /**
     * 查询在线巡考列表
     *
     * @param iPage
     * @param examId
     * @param examActivityId
     * @param roomCode
     * @param status
     * @param name
     * @param identity
     * @param minMultipleFaceCount
     * @param maxMultipleFaceCount
     * @param minExceptionCount
     * @param maxExceptionCount
     * @param minWarningCount
     * @param maxWarningCount
     * @param clientWebsocketStatus
     * @param userId
     * @param orgId
     * @return
     */
    public IPage<InvigilateListPatrolBean> invigilatePagePatrolList(IPage<Map> iPage, Long examId,
                                                                    Long examActivityId,
                                                                    String roomCode,
                                                                    String status,
                                                                    String name,
                                                                    String identity,
                                                                    Integer minMultipleFaceCount,
                                                                    Integer maxMultipleFaceCount,
                                                                    Integer minExceptionCount,
                                                                    Integer maxExceptionCount,
                                                                    Integer minWarningCount,
                                                                    Integer maxWarningCount,
                                                                    String clientWebsocketStatus,
                                                                    Long userId,
                                                                    Long orgId);

    /**
     * 预警提醒列表
     *
     * @param iPage
     * @param examId
     * @param examActivityId
     * @param roomCode
     * @param approveStatus
     * @param name
     * @param identity
     * @param minMultipleFaceCount
     * @param maxMultipleFaceCount
     * @param minExceptionCount
     * @param maxExceptionCount
     * @param minWarningCount
     * @param maxWarningCount
     * @param userId
     * @param orgId
     * @return
     */
    public IPage<InvigilateListWarningBean> invigilatePageWarningList(IPage<Map> iPage, Long examId,
                                                                      Long examActivityId,
                                                                      String roomCode,
                                                                      Integer approveStatus,
                                                                      String name,
                                                                      String identity,
                                                                      Integer minMultipleFaceCount,
                                                                      Integer maxMultipleFaceCount,
                                                                      Integer minExceptionCount,
                                                                      Integer maxExceptionCount,
                                                                      Integer minWarningCount,
                                                                      Integer maxWarningCount,
                                                                      Long userId,
                                                                      Long orgId);

    /**
     * 预警提醒清除未阅列表
     *
     * @param examId
     * @param examActivityId
     * @param roomCode
     * @param approveStatus
     * @param name
     * @param identity
     * @param minMultipleFaceCount
     * @param maxMultipleFaceCount
     * @param minExceptionCount
     * @param maxExceptionCount
     * @param minWarningCount
     * @param maxWarningCount
     * @param userId
     * @param orgId
     * @return
     */
    public Integer approveStatusListUpdate(Long examId,
                                           Long examActivityId,
                                           String roomCode,
                                           Integer approveStatus,
                                           String name,
                                           String identity,
                                           Integer minMultipleFaceCount,
                                           Integer maxMultipleFaceCount,
                                           Integer minExceptionCount,
                                           Integer maxExceptionCount,
                                           Integer minWarningCount,
                                           Integer maxWarningCount,
                                           Long userId,
                                           Long orgId);

    /**
     * 进度查询列表
     *
     * @param iPage
     * @param examId
     * @param examActivityId
     * @param roomCode
     * @param courseCode
     * @param name
     * @param identity
     * @param status
     * @param userId
     * @param orgId
     * @param breachStatus
     * @return
     */
    public IPage<InvigilateListProgressBean> invigilatePageProgressList(IPage<Map> iPage, Long examId,
                                                                        Long examActivityId,
                                                                        String roomCode,
                                                                        String courseCode,
                                                                        String name,
                                                                        String identity,
                                                                        Integer status,
                                                                        Long userId,
                                                                        Long orgId,
                                                                        Integer breachStatus);

    /**
     * 进度查询列表导出
     *
     * @param examId
     * @param examActivityId
     * @param roomCode
     * @param courseCode
     * @param name
     * @param identity
     * @param status
     * @param userId
     * @param orgId
     * @param breachStatus
     * @return
     */
    public List<InvigilateListProgressExcelBean> invigilatePageProgressListExport(Long examId,
                                                                                  Long examActivityId,
                                                                                  String roomCode,
                                                                                  String courseCode,
                                                                                  String name,
                                                                                  String identity,
                                                                                  Integer status,
                                                                                  Long userId,
                                                                                  Long orgId,
                                                                                  Integer breachStatus);

    /**
     * 监考明细管理列表
     *
     * @param iPage
     * @param examId
     * @param examActivityId
     * @param roomCode
     * @param courseCode
     * @param status
     * @param breachStatus
     * @param finishType
     * @param name
     * @param identity
     * @param minMultipleFaceCount
     * @param maxMultipleFaceCount
     * @param minExceptionCount
     * @param maxExceptionCount
     * @param minWarningCount
     * @param maxWarningCount
     * @param userId
     * @param orgId
     * @return
     */
    public IPage<InvigilateListHistoryBean> invigilatePageListHistory(IPage<Map> iPage, Long examId,
                                                                      Long examActivityId,
                                                                      String roomCode,
                                                                      String courseCode,
                                                                      String status,
                                                                      Integer breachStatus,
                                                                      String finishType,
                                                                      String name,
                                                                      String identity,
                                                                      Integer minMultipleFaceCount,
                                                                      Integer maxMultipleFaceCount,
                                                                      Integer minExceptionCount,
                                                                      Integer maxExceptionCount,
                                                                      Integer minWarningCount,
                                                                      Integer maxWarningCount,
                                                                      Long userId,
                                                                      Long orgId);

    /**
     * 监考明细管理列表导出
     *
     * @param examId
     * @param examActivityId
     * @param roomCode
     * @param courseCode
     * @param status
     * @param breachStatus
     * @param finishType
     * @param name
     * @param identity
     * @param minMultipleFaceCount
     * @param maxMultipleFaceCount
     * @param minExceptionCount
     * @param maxExceptionCount
     * @param minWarningCount
     * @param maxWarningCount
     * @param userId
     * @param orgId
     * @return
     */
    public List<InvigilateListHistoryBean> invigilatePageListHistoryExport(Long examId,
                                                                           Long examActivityId,
                                                                           String roomCode,
                                                                           String courseCode,
                                                                           String status,
                                                                           Integer breachStatus,
                                                                           String finishType,
                                                                           String name,
                                                                           String identity,
                                                                           Integer minMultipleFaceCount,
                                                                           Integer maxMultipleFaceCount,
                                                                           Integer minExceptionCount,
                                                                           Integer maxExceptionCount,
                                                                           Integer minWarningCount,
                                                                           Integer maxWarningCount,
                                                                           Long userId,
                                                                           Long orgId);


    /**
     * 重新算分
     */
    void calculateScore(Long recordId);

    /**
     * 获取考试记录数
     *
     * @param examId
     * @return
     */
    Long getCountByExamId(Long examId);

    /**
     * 批量获取考试记录
     *
     * @param examId
     * @param startId
     * @return
     */
    List<TOeExamRecord> getListByExamIdAndStartId(Long examId, Long startId);

    TOeExamRecord findOneByPaperId(Long paperId);

    TOeExamRecord findOneByExamId(Long examId, ExamRecordStatusEnum status);

    public List<OpenRecordNeedMarkBean> findExamRecordNeedMark(Long examStudentId);

    /**
     * 寻找客观分最高
     *
     * @param examId
     * @param examStudentId
     * @return
     */
    List<TOeExamRecord> findMaxObjectiveScore(Long examId, Long examStudentId);

    /**
     * 查询成绩
     *
     * @param markResultDto
     * @param recordSelectStrategyEnum
     * @return
     */
    TOeExamRecord findMarkResult(MarkResultDto markResultDto, RecordSelectStrategyEnum recordSelectStrategyEnum);

    /**
     * 设置断点信息
     *
     * @param recordId
     */
    Boolean setExamBreak(Long recordId);

    /**
     * 断点逻辑
     *
     * @param recordId
     * @param setBreak
     * @return
     */
    Boolean examBreakLogic(Long recordId, boolean setBreak);

    /**
     * 根据orgId查找 在线人数/已待考/考试人数
     *
     * @param orgId
     * @return
     */
    List<Long> findByOrgId(Long orgId);

    /**
     * 查找监控消息
     *
     * @param examId
     * @param roomCodeSet
     * @param examActivityId
     * @return
     */
    List<CountStopBean> findByStopInfo(Long examId, Set<String> roomCodeSet, Long examActivityId);

    /**
     * 查找在线消息
     *
     * @param examId
     * @param roomCodeSet
     * @param examActivityId \
     * @return
     */
    List<Integer> findByOnlineInfo(Long examId, Set<String> roomCodeSet, Long examActivityId);

    /**
     * 管理员报表
     *
     * @param orgId
     * @param examId
     * @param examActivityId
     * @param roomCode
     * @param courseCode
     * @param monitorStatus
     * @return
     */
    List<Integer> findByViewAdmin(Long orgId, Long examId, Long examActivityId, String roomCode, String courseCode, InvigilateMonitorStatusEnum monitorStatus);

    /**
     * 考试明细查询接口
     *
     * @param iPage
     * @param examId
     * @param examActivityId
     * @param courseCode
     * @param roomCode
     * @param finishType
     * @param name
     * @param identity
     * @return
     */
    public IPage<ExamRecordDetailBean> examRecordDetailQuery(IPage<Map> iPage,
                                                             Long examId,
                                                             Long examActivityId,
                                                             String courseCode,
                                                             String roomCode,
                                                             String finishType,
                                                             String name,
                                                             String identity);

    /**
     * 考试明细查询接口
     *
     * @param examId
     * @param courseCodeList
     * @param identityList
     * @return
     */
    public List<String> examRecordDetailQuery(Long examId, List<String> courseCodeList, List<String> identityList);

    /**
     * 查看试卷
     *
     * @param examRecordId
     * @return
     */
    public ExamRecordPaperViewBean examRecordPaperView(Long examRecordId) throws IOException;

    /**
     * 查询没有视频地址的考试记录
     *
     * @param examId
     * @return
     */
    public List<TOeExamRecord> findExamRecordByNotVideoUrl(Long examId);

    /**
     * 根据考试批次id和场次id查找考试数据
     *
     * @param examId
     * @param examActivityId
     * @return
     */
    public List<TOeExamRecord> findExamRecordByExamIdAndExamActivityId(Long examId, Long examActivityId);

    /**
     * 根据考试批次id或考试场次id查找
     *
     * @param examId
     * @param examActivityId
     * @return
     */
    public Integer findByExamIdOrExamActivityIdCount(Long examId, Long examActivityId);

    /**
     * 获取所有待阅卷的考试记录
     *
     * @param examId
     * @param examPaperIdSet
     * @param many
     * @param examStudentBreachPush
     * @return
     */
    public List<TOeExamRecord> findExamRecordNeedMarkAll(Long examId, Set<Long> examPaperIdSet, Boolean many, Boolean examStudentBreachPush);

    /**
     * 修正作答记录缓存到数据库
     *
     * @param examId
     * @param examActivityId
     * @param status
     * @return
     */
    public List<TOeExamRecord> persistedAnswerBatch(Long examId, Long examActivityId, ExamRecordStatusEnum status);

    /**
     * 考试记录数据持久化
     *
     * @param recordId
     */
    public void saveDataByCachePersistedAnswer(Long recordId);

    /**
     * 修正考试状态
     *
     * @return
     */
    public List<TOeExamRecord> updateExamStatus();

    /**
     * 清除考试缓存
     *
     * @param examIds
     * @return
     */
    public List<Map> cleanExamFirstPrepareCache(Set<Long> examIds);

    /**
     * 数据统计
     *
     * @return
     */
    List<Long> dataCount();

    /**
     * 机构数据统计
     *
     * @return
     */
    List<OrgDataCountBean> orgDataCount();

    /**
     * 地图数据统计
     *
     * @return
     */
    List<MapDataCountBean> mapDataCount();

    /**
     * 从缓存里获取考试记录
     *
     * @param recordId
     * @return
     */
    TOeExamRecord getCacheExamRecord(Long recordId);

    /**
     * 从数据库查询考试记录
     *
     * @param examId
     * @param activityId
     * @param examStudentId
     * @param examRecordStatusEnum
     * @return
     */
    TOeExamRecord getExamRecordForDb(Long examId, Long activityId, Long examStudentId, ExamRecordStatusEnum examRecordStatusEnum);

    /**
     * 根据id更新预警数量
     *
     * @param id
     */
    void updateWarningCountByDb(Long id);

    /**
     * 根据id更新预警未读数量
     *
     * @param id
     * @param number
     */
    void updateWarningUnreadByDb(Long id, Integer number);

    /**
     * 更新预警总数
     *
     * @param id
     * @param tIeInvigilateWarnInfo
     */
    void updateWarningCountCache(Long id, TIeInvigilateWarnInfo tIeInvigilateWarnInfo);

    /**
     * 更新预警未读数
     *
     * @param id
     * @param number
     * @param updateDb
     */
    void updateWarningUnreadCache(Long id, Integer number, Boolean updateDb);

    /**
     * 更新陌生人脸预警总数
     *
     * @param id
     */
    void updateWarningMultipleFaceCountCache(Long id);

    /**
     * 更新异常数
     *
     * @param id
     */
    void updateExceptionCountCache(Long id);

    /**
     * 根据预警条件清除未阅
     *
     * @param examId
     * @param examActivityId
     * @param roomCode
     * @param name
     * @param identity
     * @param minMultipleFaceCount
     * @param maxMultipleFaceCount
     * @param minExceptionCount
     * @param maxExceptionCount
     * @param minWarningCount
     * @param maxWarningCount
     * @param userId
     * @param orgId
     * @return
     */
    List<TOeExamRecord> findExamRecordByWarning(Long examId,
                                                Long examActivityId,
                                                String roomCode,
                                                String name,
                                                String identity,
                                                Integer minMultipleFaceCount,
                                                Integer maxMultipleFaceCount,
                                                Integer minExceptionCount,
                                                Integer maxExceptionCount,
                                                Integer minWarningCount,
                                                Integer maxWarningCount,
                                                Long userId,
                                                Long orgId);

    /**
     * 查找完成人数
     *
     * @param examId
     * @param examActivityId
     * @param roomCode
     * @return
     */
    Integer findExamRecordByFinish(Long examId, Long examActivityId, String roomCode);
}