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

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qmth.themis.business.bean.admin.ExamListBean;
import com.qmth.themis.business.cache.bean.ExamCacheBean;
import com.qmth.themis.business.constant.SpringContextHolder;
import com.qmth.themis.business.constant.SystemConstant;
import com.qmth.themis.business.dto.AuthDto;
import com.qmth.themis.business.dto.cache.TEStudentCacheDto;
import com.qmth.themis.business.entity.*;
import com.qmth.themis.business.enums.RoleEnum;
import com.qmth.themis.business.service.*;
import com.qmth.themis.business.util.RedisUtil;
import com.qmth.themis.common.enums.ExceptionResultEnum;
import com.qmth.themis.common.exception.BusinessException;
import com.qmth.themis.common.util.GsonUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.stream.Collectors;

/**
 * @Description: 缓存 服务实现类
 * @Param:
 * @return:
 * @Author: wangliang
 * @Date: 2020/6/27
 */
@Service
public class ThemisCacheServiceImpl implements ThemisCacheService {
    private final static Logger log = LoggerFactory.getLogger(ThemisCacheServiceImpl.class);

    @Resource
    TBUserRoleService tbUserRoleService;

    @Resource
    TBPrivilegeService tbPrivilegeService;

    @Resource
    TBRolePrivilegeService tbRolePrivilegeService;

    @Resource
    TBUserService tbUserService;

    @Resource
    TBOrgService tbOrgService;

    @Resource
    TEStudentService teStudentService;

    @Resource
    SysConfigService sysConfigService;

    @Resource
    TEAudioService teAudioService;

    @Resource
    TBAttachmentService tbAttachmentService;

    @Resource
    CacheManager cacheManager;

    @Resource
    TSBlackListService tsBlackListService;

    @Resource
    TSNotifyService tsNotifyService;

    @Resource
    TBProblemService tbProblemService;

    @Resource
    RedisUtil redisUtil;

    @Resource
    TEExamActivityService teExamActivityService;

    @Resource
    TEExamStudentService teExamStudentService;

    @Resource
    TEExamSummaryService teExamSummaryService;

    @Resource
    TEExamService teExamService;

    @Resource
    TEOrgSummaryService teOrgSummaryService;

    @Resource
    TERegionSummaryService teRegionSummaryService;

    /**
     * 添加机构缓存
     *
     * @param orgId
     * @return
     */
    @Override
    @Cacheable(value = SystemConstant.orgCache, key = "#p0", unless = "#result == null")
    public TBOrg addOrgCache(Long orgId) {
        return tbOrgService.getById(orgId);
    }

    /**
     * 更新机构缓存
     *
     * @param orgId
     * @return
     */
    @Override
    @CachePut(value = SystemConstant.orgCache, key = "#p0", condition = "#result != null")
    public TBOrg updateOrgCache(Long orgId) {
        return tbOrgService.getById(orgId);
    }

    /**
     * 添加机构编码缓存
     *
     * @param code
     * @return
     */
    @Override
    @Cacheable(value = SystemConstant.orgCodeCache, key = "#p0", unless = "#result == null")
    public TBOrg addOrgCodeCache(String code) {
        TBOrg tbOrg = tbOrgService.getOne(new QueryWrapper<TBOrg>().lambda().eq(TBOrg::getCode, code));
        Optional.ofNullable(tbOrg).orElseThrow(() -> new BusinessException(ExceptionResultEnum.ORG_NO));
        return tbOrg;
    }

    /**
     * 更新机构编码缓存
     *
     * @param code
     * @return
     */
    @Override
    @CachePut(value = SystemConstant.orgCodeCache, key = "#p0", condition = "#result != null")
    public TBOrg updateOrgCodeCache(String code) {
        QueryWrapper<TBOrg> tbOrgQueryWrapper = new QueryWrapper<>();
        tbOrgQueryWrapper.lambda().eq(TBOrg::getCode, code);
        return tbOrgService.getOne(tbOrgQueryWrapper);
    }

    /**
     * 删除机构缓存
     *
     * @param orgId
     */
    @Override
    @CacheEvict(value = SystemConstant.orgCache, key = "#p0")
    public void removeOrgCache(Long orgId) {

    }

    /**
     * 删除机构编码缓存
     *
     * @param code
     */
    @Override
    @CacheEvict(value = SystemConstant.orgCodeCache, key = "#p0")
    public void removeOrgCodeCache(String code) {

    }

    /**
     * 删除机构缓存
     */
    @Override
    @CacheEvict(value = SystemConstant.orgCache, allEntries = true)
    public void removeOrgIdCache() {

    }

    /**
     * 删除机构缓存
     */
    @Override
    @CacheEvict(value = SystemConstant.orgCodeCache, allEntries = true)
    public void removeOrgCodeCache() {

    }

    /**
     * 添加用户缓存
     *
     * @param userId
     * @return
     */
    @Override
    @Cacheable(value = SystemConstant.userOauth, key = "#p0", unless = "#result == null")
    public AuthDto addAccountAuthCache(Long userId) {
        AuthDto authDto = null;
        try {
            ThemisCacheService themisCacheService = SpringContextHolder.getBean(ThemisCacheService.class);
            TBUser user = themisCacheService.addAccountCache(userId);
            if (Objects.isNull(user)) {
                throw new BusinessException(ExceptionResultEnum.USER_NO);
            }
            //查询用户角色和权限
            QueryWrapper<TBUserRole> uWrapper = new QueryWrapper<>();
            uWrapper.lambda().eq(TBUserRole::getUserId, user.getId());
            List<TBUserRole> tbUserRoleList = tbUserRoleService.list(uWrapper);
            if (Objects.nonNull(tbUserRoleList)) {
                TBOrg tbOrg = Objects.nonNull(user.getOrgId()) ? themisCacheService.addOrgCache(user.getOrgId()) : null;
                //根据角色名查权限
                Set<String> roleCodes = tbUserRoleList.stream().map(s -> s.getRoleCode()).collect(Collectors.toSet());
                QueryWrapper<TBRolePrivilege> rpWrapper = new QueryWrapper<>();
                rpWrapper.lambda().in(TBRolePrivilege::getRoleCode, roleCodes);
                List<TBRolePrivilege> tbRolePrivilegeList = tbRolePrivilegeService.list(rpWrapper);
                Set<Long> privilegeIds = tbRolePrivilegeList.stream().map(s -> s.getPrivilegeId()).collect(Collectors.toSet());
                QueryWrapper<TBPrivilege> pWrapper = new QueryWrapper<>();
                pWrapper.lambda().in(TBPrivilege::getId, privilegeIds).eq(TBPrivilege::getType, SystemConstant.LINK);
                List<TBPrivilege> tbPrivilegeList = tbPrivilegeService.list(pWrapper);
                authDto = new AuthDto(roleCodes, tbPrivilegeList.stream().map(s -> s.getUrl()).collect(Collectors.toSet()), tbOrg);
            }
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
            throw new BusinessException("添加用户鉴权缓存失败");
        }
        return authDto;
    }

    /**
     * 删除用户鉴权缓存
     *
     * @param userId
     */
    @Override
    @CacheEvict(value = SystemConstant.userOauth, key = "#p0")
    public void removeAccountAuthCache(Long userId) {

    }

    /**
     * 添加用户缓存
     *
     * @param userId
     * @return
     */
    @Override
    @Cacheable(value = SystemConstant.userAccount, key = "#p0", unless = "#result == null")
    public TBUser addAccountCache(Long userId) {
        return tbUserService.getById(userId);
    }

    /**
     * 更新用户缓存
     *
     * @param userId
     * @return
     */
    @Override
    @CachePut(value = SystemConstant.userAccount, key = "#p0", condition = "#result != null")
    public TBUser updateAccountCache(Long userId) {
        return tbUserService.getById(userId);
    }

    /**
     * 删除用户缓存
     *
     * @param userId
     */
    @Override
    @CacheEvict(value = SystemConstant.userAccount, key = "#p0")
    public void removeAccountCache(Long userId) {

    }

    /**
     * 添加学生鉴权缓存
     *
     * @param studentId
     * @return
     */
    @Override
    @Cacheable(value = SystemConstant.studentOauth, key = "#p0", unless = "#result == null")
    public AuthDto addStudentAuthCache(Long studentId) {
        AuthDto authDto = null;
        try {
            ThemisCacheService themisCacheService = SpringContextHolder.getBean(ThemisCacheService.class);
            TEStudentCacheDto teStudentCacheDto = themisCacheService.addStudentAccountCache(studentId);
            if (Objects.isNull(teStudentCacheDto)) {
                throw new BusinessException(ExceptionResultEnum.STUDENT_NO);
            }
            TBOrg tbOrg = themisCacheService.addOrgCache(teStudentCacheDto.getOrgId());
            //根据学生角色查权限
            QueryWrapper<TBRolePrivilege> rpWrapper = new QueryWrapper<>();
            rpWrapper.lambda().eq(TBRolePrivilege::getRoleCode, RoleEnum.STUDENT.name());
            List<TBRolePrivilege> tbRolePrivilegeList = tbRolePrivilegeService.list(rpWrapper);
            Set<Long> privilegeIds = tbRolePrivilegeList.stream().map(s -> s.getPrivilegeId()).collect(Collectors.toSet());
            QueryWrapper<TBPrivilege> pWrapper = new QueryWrapper<>();
            pWrapper.lambda().in(TBPrivilege::getId, privilegeIds).eq(TBPrivilege::getType, SystemConstant.LINK);
            List<TBPrivilege> tbPrivilegeList = tbPrivilegeService.list(pWrapper);
            Set<String> roleCodes = new HashSet<>();
            roleCodes.add(RoleEnum.STUDENT.name());
            authDto = new AuthDto(roleCodes, tbPrivilegeList.stream().map(s -> s.getUrl()).collect(Collectors.toSet()), tbOrg);
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
            throw new BusinessException("添加学生鉴权缓存失败");
        }
        return authDto;
    }

    /**
     * 删除学生鉴权缓存
     *
     * @param studentId
     */
    @Override
    @CacheEvict(value = SystemConstant.studentOauth, key = "#p0")
    public void removeStudentAuthCache(Long studentId) {

    }

    /**
     * 添加学生缓存
     *
     * @param studentId
     * @return
     */
    @Override
    @Cacheable(value = SystemConstant.studentAccount, key = "#p0", unless = "#result == null")
    public TEStudentCacheDto addStudentAccountCache(Long studentId) {
        TEStudent teStudent = teStudentService.getById(studentId);
        return GsonUtil.fromJson(GsonUtil.toJson(teStudent), TEStudentCacheDto.class);
    }

    /**
     * 更新学生缓存
     *
     * @param studentId
     * @return
     */
    @Override
    @CachePut(value = SystemConstant.studentAccount, key = "#p0", condition = "#result != null")
    public TEStudentCacheDto updateStudentAccountCache(Long studentId) {
        TEStudent teStudent = teStudentService.getById(studentId);
        return GsonUtil.fromJson(GsonUtil.toJson(teStudent), TEStudentCacheDto.class);
    }

    /**
     * 删除学生缓存
     *
     * @param studentId
     */
    @Override
    @CacheEvict(value = SystemConstant.studentAccount, key = "#p0")
    public void removeStudentAccountCache(Long studentId) {

    }

    /**
     * 添加系统参数缓存
     *
     * @param key
     * @return
     */
    @Override
    @Cacheable(value = SystemConstant.sysConfigCache, key = "#p0", unless = "#result == null")
    public SysConfig addSysConfigCache(String key) {
        return sysConfigService.getOne(new QueryWrapper<SysConfig>().lambda().eq(SysConfig::getConfigKey, key));
    }

    /**
     * 更新系统参数缓存
     *
     * @param key
     * @return
     */
    @Override
    @CachePut(value = SystemConstant.sysConfigCache, key = "#p0", condition = "#result != null")
    public SysConfig updateSysConfigCache(String key) {
        return sysConfigService.getOne(new QueryWrapper<SysConfig>().lambda().eq(SysConfig::getConfigKey, key));
    }

    /**
     * 删除系统参数缓存
     *
     * @param key
     */
    @Override
    @CacheEvict(value = SystemConstant.sysConfigCache, key = "#p0")
    public void removeSysConfigCache(String key) {

    }

//    @Override
//    @Cacheable(value = SystemConstant.AUTH_INFO_CACHE, key = "#p0", unless = "#result == null")
//    public AuthOrgInfoDto authInfoCache(String code) {
//        AppInfo appInfo = solarService.getAppInfo();
//        AuthOrgInfoDto authOrgInfoDto = null;
//        if (Objects.nonNull(appInfo)) {
//            List<OrgInfo> orgInfoList = solarService.getOrgList().stream().filter(s -> Objects.equals(s.getCode(), code)).collect(Collectors.toList());
//            if (Objects.nonNull(orgInfoList) && orgInfoList.size() > 0) {
//                authOrgInfoDto = new AuthOrgInfoDto(orgInfoList.get(0), appInfo.getControl());
//            }
//        }
//        return authOrgInfoDto;
//    }
//
//    @Override
//    @CachePut(value = SystemConstant.AUTH_INFO_CACHE, key = "#p0", condition = "#result != null")
//    public AuthOrgInfoDto updateAuthInfoCache(String code) {
//        AppInfo appInfo = solarService.getAppInfo();
//        AuthOrgInfoDto authOrgInfoDto = null;
//        if (Objects.nonNull(appInfo)) {
//            List<OrgInfo> orgInfoList = solarService.getOrgList().stream().filter(s -> Objects.equals(s.getCode(), code)).collect(Collectors.toList());
//            if (Objects.nonNull(orgInfoList) && orgInfoList.size() > 0) {
//                authOrgInfoDto = new AuthOrgInfoDto(orgInfoList.get(0), appInfo.getControl());
//            }
//        }
//        return authOrgInfoDto;
//    }
//
//    @Override
//    @CacheEvict(value = SystemConstant.AUTH_INFO_CACHE, key = "#p0")
//    public void removeAuthInfoCache(String code) {
//
//    }

    /**
     * 添加考试语音缓存
     *
     * @param id
     * @return
     */
    @Override
    @Cacheable(value = SystemConstant.EXAM_AUDIO_CACHE, key = "#p0", unless = "#result == null")
    public TEAudio examAudioCache(Long id) {
        return teAudioService.getById(id);
    }

    /**
     * 修改考试语音缓存
     *
     * @param id
     * @return
     */
    @Override
    @CachePut(value = SystemConstant.EXAM_AUDIO_CACHE, key = "#p0", condition = "#result != null")
    public TEAudio updateExamAudioCache(Long id) {
        return teAudioService.getById(id);
    }

    /**
     * 删除考试语音缓存
     *
     * @param id
     */
    @Override
    @CacheEvict(value = SystemConstant.EXAM_AUDIO_CACHE, key = "#p0")
    public void removeExamAudioCache(Long id) {

    }

    /**
     * 添加附件缓存
     *
     * @param id
     * @return
     */
    @Override
    @Cacheable(value = SystemConstant.ATTACHMENT_CACHE, key = "#p0", unless = "#result == null")
    public TBAttachment attachmentCache(Long id) {
        return tbAttachmentService.getById(id);
    }

    /**
     * 修改附件缓存
     *
     * @param id
     * @return
     */
    @Override
    @CachePut(value = SystemConstant.ATTACHMENT_CACHE, key = "#p0", condition = "#result != null")
    public TBAttachment updateAttachmentCache(Long id) {
        return tbAttachmentService.getById(id);
    }

    /**
     * 删除附件缓存
     *
     * @param id
     */
    @Override
    @CacheEvict(value = SystemConstant.ATTACHMENT_CACHE, key = "#p0")
    public void removeAttachmentCache(Long id) {

    }

    /**
     * 更新系统参数缓存
     *
     * @param key
     * @return
     */
    @Override
    public void updateSysConfigCacheForDb(String key, SysConfig sysConfig) {
        cacheManager.getCache(SystemConstant.sysConfigCache).put(key, sysConfig);
    }

    /**
     * 黑名单缓存
     *
     * @return
     */
    @Override
    @Cacheable(value = SystemConstant.BLACK_LIST_CACHE, unless = "#result == null")
    public List<TSBlackList> blackListCache() {
        return tsBlackListService.list(new QueryWrapper<TSBlackList>().lambda().eq(TSBlackList::getEnable, true));
    }

    /**
     * 修改黑名单缓存
     *
     * @return
     */
    @Override
    @CachePut(value = SystemConstant.BLACK_LIST_CACHE, condition = "#result != null")
    public List<TSBlackList> updateBlackListCache() {
        return tsBlackListService.list(new QueryWrapper<TSBlackList>().lambda().eq(TSBlackList::getEnable, true));
    }

    /**
     * 删除黑名单缓存
     */
    @Override
    @CacheEvict(value = SystemConstant.BLACK_LIST_CACHE)
    public void removeBlackListCache() {

    }

    /**
     * 系统通知缓存
     *
     * @return
     */
    @Override
    @Cacheable(value = SystemConstant.SYS_NOTIFY_CACHE, unless = "#result == null")
    public List<TSNotify> sysNotifyCache() {
        return tsNotifyService.list(new QueryWrapper<TSNotify>().lambda().eq(TSNotify::getEnable, true));
    }

    /**
     * 修改系统通知缓存
     *
     * @return
     */
    @Override
    @CachePut(value = SystemConstant.SYS_NOTIFY_CACHE, condition = "#result != null")
    public List<TSNotify> updateSysNotifyCache() {
        return tsNotifyService.list(new QueryWrapper<TSNotify>().lambda().eq(TSNotify::getEnable, true));
    }

    /**
     * 删除系统通知缓存
     */
    @Override
    @CacheEvict(value = SystemConstant.SYS_NOTIFY_CACHE)
    public void removeSysNotifyCache() {

    }

    /**
     * 问题缓存
     *
     * @return
     */
    @Override
    @Cacheable(value = SystemConstant.PROBLEM_CACHE, unless = "#result == null")
    public List<TBProblem> problemCache() {
        return tbProblemService.list(new QueryWrapper<TBProblem>().lambda().eq(TBProblem::getEnable, true));
    }

    /**
     * 修改问题缓存
     *
     * @return
     */
    @Override
    @CachePut(value = SystemConstant.PROBLEM_CACHE, condition = "#result != null")
    public List<TBProblem> updateProblemCache() {
        return tbProblemService.list(new QueryWrapper<TBProblem>().lambda().eq(TBProblem::getEnable, true));
    }

    /**
     * 删除问题缓存
     */
    @Override
    @CacheEvict(value = SystemConstant.PROBLEM_CACHE)
    public void removeProblemCache() {

    }

    /**
     * 设置当前考试缓存
     */
    @Override
    public void setCurrentExamListCache() {
        try {
            Date now = new Date();
            SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
            String current = sdf1.format(now);
            SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Long startTime = sdf2.parse(current + " 00:00:00").getTime();
            Long endTime = sdf2.parse(current + " 23:59:59").getTime();
            List<TEExamActivity> teExamActivityList = teExamActivityService.findCurrentExamActivity(startTime, endTime);
            //统计当天00:00:00~23:59:59可以进行的考试批次、场次、考场编码信息
            if (!CollectionUtils.isEmpty(teExamActivityList)) {
                LinkedMultiValueMap<Long, ExamListBean> currentExamListMap = new LinkedMultiValueMap<>();//考试批次、场次集合/考场编码集合
                Map<Long, Set<Long>> examActivityIdMap = new HashMap<>();//考试批次id，场次id集合
                Map<Long, Set<String>> roomCodeMap = new HashMap<>();//考试场次id，考场编码集合
                for (TEExamActivity t : teExamActivityList) {
                    List<TEExamStudent> teExamStudentList = teExamStudentService.list(new QueryWrapper<TEExamStudent>().lambda().eq(TEExamStudent::getExamId, t.getExamId()).eq(TEExamStudent::getExamActivityId, t.getId()));
                    if (!CollectionUtils.isEmpty(teExamStudentList)) {
                        Set<String> roomCodeSet = teExamStudentList.stream().map(s -> s.getRoomCode()).collect(Collectors.toSet());
                        if (examActivityIdMap.containsKey(t.getExamId())) {
                            Set<Long> examActivityIdSet = examActivityIdMap.get(t.getExamId());
                            examActivityIdSet.add(t.getId());
                            examActivityIdMap.put(t.getExamId(), examActivityIdSet);
                        } else {
                            examActivityIdMap.put(t.getExamId(), new HashSet<>(Arrays.asList(t.getId())));
                        }
                        roomCodeMap.put(t.getId(), roomCodeSet);
                    }
                }
                examActivityIdMap.forEach((k, v) -> {
                    for (Long l : v) {
                        String s = StringUtils.join(roomCodeMap.get(l)).replaceAll("\\[", "").replaceAll("\\]", "");
                        currentExamListMap.add(k, new ExamListBean(l, s));
                    }
                });
                currentExamListMap.forEach((k, v) -> {
                    redisUtil.set(SystemConstant.CURRENT_EXAM_LIST_MAP_CACHE, k.toString(), v);
                });
            }
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
        }
    }

    /**
     * 获取当前考试列表缓存
     *
     * @return
     */
    @Override
    public Map<String, List<ExamListBean>> getCurrentExamListCache() {
        return redisUtil.getHashEntries(SystemConstant.CURRENT_EXAM_LIST_MAP_CACHE);
    }

    /**
     * 设置考试列表缓存
     */
    @Override
    public void setOrgExamListCache() {
        SysConfig sysConfig = this.addSysConfigCache(SystemConstant.WAITING_EXAM_DAY);
        Optional.ofNullable(sysConfig).orElseThrow(() -> new BusinessException("未配置待考列表天数"));

        //查询提前3天待考的考试列表
        List<TEExamActivity> teExamActivityList = teExamActivityService.findWaitingExamList(Integer.parseInt(sysConfig.getConfigValue()));
        if (!CollectionUtils.isEmpty(teExamActivityList)) {
            Map<Long, Set<Long>> orgMap = new HashMap<>();//机构id，考试批次id集合
            Map<Long, Set<Long>> examMap = new HashMap<>();//考试批次id，场次id集合
            for (TEExamActivity t : teExamActivityList) {
                ExamCacheBean examCacheBean = teExamService.getExamCacheBean(t.getExamId());
                if (orgMap.containsKey(examCacheBean.getOrgId())) {
                    Set<Long> examIdSet = orgMap.get(examCacheBean.getOrgId());
                    examIdSet.add(t.getExamId());
                    orgMap.put(examCacheBean.getOrgId(), examIdSet);
                } else {
                    orgMap.put(examCacheBean.getOrgId(), new HashSet<>(Arrays.asList(t.getExamId())));
                }
                if (examMap.containsKey(t.getExamId())) {
                    Set<Long> examActivityIdSet = examMap.get(examCacheBean.getId());
                    examActivityIdSet.add(t.getId());
                    examMap.put(t.getExamId(), examActivityIdSet);
                } else {
                    examMap.put(t.getExamId(), new HashSet<>(Arrays.asList(t.getId())));
                }
            }
            orgMap.forEach((k, v) -> {
                for (Long l : v) {
                    redisUtil.set(SystemConstant.ORG_EXAM_LIST_MAP_CACHE + k, l.toString(), examMap.get(l));
                }
            });
        }
    }

    /**
     * 获取机构考试列表缓存
     *
     * @param orgId
     * @return
     */
    @Override
    public Map<String, Set<Long>> getOrgExamListCache(String orgId) {
        return redisUtil.getHashEntries(SystemConstant.ORG_EXAM_LIST_MAP_CACHE + orgId);
    }

    /**
     * 获取机构考试列表缓存
     *
     * @param orgId
     * @param examId
     * @return
     */
    @Override
    public Set<Long> getOrgExamListCache(String orgId, String examId) {
        Map<String, Set<Long>> map = this.getOrgExamListCache(orgId);
        return !CollectionUtils.isEmpty(map) ? map.get(examId) : null;
    }

    /**
     * @param orgId
     * @param examId
     * @param examActivityId
     */
    @Override
    public void updateOrgExamListCache(String orgId, String examId, Long examActivityId) {
        Map<String, Set<Long>> map = this.getOrgExamListCache(orgId);
        if (CollectionUtils.isEmpty(map)) {
            redisUtil.set(SystemConstant.ORG_EXAM_LIST_MAP_CACHE + orgId, examId, new HashSet<>(Arrays.asList(examActivityId)));
        } else {
            Set<Long> examActivityIdSet = map.get(examId);
            if (Objects.isNull(examActivityIdSet)) {
                examActivityIdSet = new HashSet<>();
            }
            examActivityIdSet.add(examActivityId);
            redisUtil.set(SystemConstant.ORG_EXAM_LIST_MAP_CACHE + orgId, examId, examActivityIdSet);
        }
    }

    /**
     * 删除机构考试列表缓存
     *
     * @param orgId
     */
    @Override
    public void removeOrgExamListCache(String orgId) {
        redisUtil.delete(SystemConstant.ORG_EXAM_LIST_MAP_CACHE + orgId);
    }

    /**
     * 删除机构考试列表缓存
     *
     * @param orgId
     * @param examId
     */
    @Override
    public void removeOrgExamListCache(String orgId, String examId) {
        redisUtil.delete(SystemConstant.ORG_EXAM_LIST_MAP_CACHE + orgId, examId);
    }

    /**
     * 删除机构考试列表缓存
     *
     * @param orgId
     * @param examId
     * @param examActivityId
     */
    @Override
    public void removeOrgExamListCache(String orgId, String examId, Long examActivityId) {
        Map<String, Set<Long>> map = this.getOrgExamListCache(orgId);
        if (!CollectionUtils.isEmpty(map.get(examId))) {
            CopyOnWriteArraySet<Long> examActivityIdSet = new CopyOnWriteArraySet<>();
            examActivityIdSet.addAll(map.get(examId));
            for (Long l : examActivityIdSet) {
                if (l.longValue() == examActivityId.longValue()) {
                    examActivityIdSet.remove(l);
                    break;
                }
            }
            if (CollectionUtils.isEmpty(examActivityIdSet)) {
                this.removeOrgExamListCache(orgId, examId);
            } else {
                redisUtil.set(SystemConstant.ORG_EXAM_LIST_MAP_CACHE + orgId, examId, new HashSet<>(examActivityIdSet));
            }
            map = this.getOrgExamListCache(orgId);
            if (CollectionUtils.isEmpty(map)) {
                this.removeOrgExamListCache(orgId);
            }
        }
    }

    /**
     * 获取当前考试列表缓存
     *
     * @param examId
     * @return
     */
    @Override
    public List<ExamListBean> getCurrentExamListCache(String examId) {
        Map<String, List<ExamListBean>> map = this.getCurrentExamListCache();
        return !CollectionUtils.isEmpty(map) ? map.get(examId) : null;
    }

    /**
     * 更新当前考试缓存
     *
     * @param examId
     * @return
     */
    @Override
    public void updateCurrentExamListCache(String examId, Long examActivityId) {
        List<TEExamStudent> teExamStudentList = teExamStudentService.list(new QueryWrapper<TEExamStudent>().lambda().eq(TEExamStudent::getExamId, Long.parseLong(examId)).eq(TEExamStudent::getExamActivityId, examActivityId));
        if (!CollectionUtils.isEmpty(teExamStudentList)) {
            Set<String> roomCodeSet = teExamStudentList.stream().map(s -> s.getRoomCode()).collect(Collectors.toSet());
            this.removeCurrentExamListCache(examId, examActivityId);
            List<ExamListBean> examListBeanList = this.getCurrentExamListCache(examId);
            CopyOnWriteArrayList<ExamListBean> copyOnWriteArrayList = !CollectionUtils.isEmpty(examListBeanList) ? new CopyOnWriteArrayList(examListBeanList) : new CopyOnWriteArrayList();
            copyOnWriteArrayList.add(new ExamListBean(examActivityId, StringUtils.join(roomCodeSet).replaceAll("\\[", "").replaceAll("\\]", "")));
            redisUtil.set(SystemConstant.CURRENT_EXAM_LIST_MAP_CACHE, examId, new LinkedList<>(copyOnWriteArrayList));
        }
    }

    /**
     * 删除当天考试缓存
     *
     * @param examId
     */
    @Override
    public void removeCurrentExamListCache(String examId) {
        redisUtil.delete(SystemConstant.CURRENT_EXAM_LIST_MAP_CACHE, examId);
    }

    /**
     * 删除当天考试缓存
     *
     * @param examId
     * @param examActivityId
     */
    @Override
    public void removeCurrentExamListCache(String examId, Long examActivityId) {
        List<ExamListBean> examListBeanList = this.getCurrentExamListCache(examId);
        if (!CollectionUtils.isEmpty(examListBeanList)) {
            CopyOnWriteArrayList<ExamListBean> copyOnWriteArrayList = new CopyOnWriteArrayList(examListBeanList);
            for (ExamListBean e : copyOnWriteArrayList) {
                if (e.getExamActivityId().longValue() == examActivityId.longValue()) {
                    copyOnWriteArrayList.remove(e);
                    break;
                }
            }
            if (!CollectionUtils.isEmpty(copyOnWriteArrayList)) {
                redisUtil.set(SystemConstant.CURRENT_EXAM_LIST_MAP_CACHE, examId, new LinkedList<>(copyOnWriteArrayList));
            } else {
                this.removeCurrentExamListCache(examId);
            }
        }
    }

    /**
     * 查询考试统计信息公用
     *
     * @param examId
     * @param examActivityId
     * @param roomCode
     * @return
     */
    protected List<TEExamSummary> examSummaryQueryCommon(Long examId, Long examActivityId, String roomCode) {
        QueryWrapper<TEExamSummary> teExamSummaryQueryWrapper = new QueryWrapper<>();
        teExamSummaryQueryWrapper.lambda().eq(TEExamSummary::getExamId, examId);
        if (Objects.nonNull(examActivityId)) {
            teExamSummaryQueryWrapper.lambda().eq(TEExamSummary::getExamActivityId, examActivityId);
        }
        if (Objects.nonNull(roomCode)) {
            teExamSummaryQueryWrapper.lambda().eq(TEExamSummary::getRoomCode, roomCode);
        }
        return teExamSummaryService.list(teExamSummaryQueryWrapper);
    }

    /**
     * 获取考试统计缓存
     *
     * @param examId
     * @return
     */
    @Override
    @Cacheable(value = SystemConstant.examSummaryCache, key = "#p0", unless = "#result?.size() == 0")
    public List<TEExamSummary> getExamSummaryCache(Long examId) {
        return this.examSummaryQueryCommon(examId, null, null);
    }

    /**
     * 获取考试统计缓存
     *
     * @param examId
     * @param examActivityId
     * @return
     */
    @Override
    @Cacheable(value = SystemConstant.examSummaryCache, key = "#p0 + '-' + #p1", unless = "#result?.size() == 0")
    public List<TEExamSummary> getExamSummaryCache(Long examId, Long examActivityId) {
        return this.examSummaryQueryCommon(examId, examActivityId, null);
    }

    /**
     * 获取考试统计缓存
     *
     * @param examId
     * @param examActivityId
     * @param roomCode
     * @return
     */
    @Override
    @Cacheable(value = SystemConstant.examSummaryCache, key = "#p0 + '-' + #p1 + '-' + #p2", unless = "#result?.size() == 0")
    public List<TEExamSummary> getExamSummaryCache(Long examId, Long examActivityId, String roomCode) {
        return this.examSummaryQueryCommon(examId, examActivityId, roomCode);
    }

    /**
     * 修改考试统计缓存
     *
     * @param examId
     * @return
     */
    @Override
    @CachePut(value = SystemConstant.examSummaryCache, key = "#p0", condition = "#result?.size() > 0")
    public List<TEExamSummary> updateExamSummaryCache(Long examId) {
        return this.examSummaryQueryCommon(examId, null, null);
    }

    /**
     * 修改考试统计缓存
     *
     * @param examId
     * @param examActivityId
     * @return
     */
    @Override
    @CachePut(value = SystemConstant.examSummaryCache, key = "#p0 + '-' + #p1", condition = "#result?.size() > 0")
    public List<TEExamSummary> updateExamSummaryCache(Long examId, Long examActivityId) {
        return this.examSummaryQueryCommon(examId, examActivityId, null);
    }

    /**
     * 修改考试统计缓存
     *
     * @param examId
     * @param examActivityId
     * @param roomCode
     * @return
     */
    @Override
    @CachePut(value = SystemConstant.examSummaryCache, key = "#p0 + '-' + #p1 + '-' + #p2", condition = "#result?.size() > 0")
    public List<TEExamSummary> updateExamSummaryCache(Long examId, Long examActivityId, String roomCode) {
        return this.examSummaryQueryCommon(examId, examActivityId, roomCode);
    }

    /**
     * 删除考试统计缓存
     *
     * @param examId
     */
    @Override
    @CacheEvict(value = SystemConstant.examSummaryCache, key = "#p0")
    public void removeExamSummaryCache(Long examId) {

    }

    /**
     * 删除考试统计缓存
     *
     * @param examId
     * @param examActivityId
     */
    @Override
    @CacheEvict(value = SystemConstant.examSummaryCache, key = "#p0 + '-' + #p1")
    public void removeExamSummaryCache(Long examId, Long examActivityId) {

    }

    /**
     * 删除考试统计缓存
     *
     * @param examId
     * @param examActivityId
     * @param roomCode
     */
    @Override
    @CacheEvict(value = SystemConstant.examSummaryCache, key = "#p0 + '-' + #p1 + '-' + #p2")
    public void removeExamSummaryCache(Long examId, Long examActivityId, String roomCode) {

    }

    /**
     * 获取机构统计缓存
     *
     * @param orgId
     * @return
     */
    @Override
    @Cacheable(value = SystemConstant.orgSummaryCache, key = "#p0", unless = "#result == null")
    public TEOrgSummary getOrgSummaryCache(Long orgId) {
        return teOrgSummaryService.getOne(new QueryWrapper<TEOrgSummary>().lambda().eq(TEOrgSummary::getOrgId, orgId));
    }

    /**
     * 更新机构统计缓存
     *
     * @param orgId
     * @return
     */
    @Override
    @CachePut(value = SystemConstant.orgSummaryCache, key = "#p0", condition = "#result != null")
    public TEOrgSummary updateOrgSummaryCache(Long orgId) {
        return teOrgSummaryService.getOne(new QueryWrapper<TEOrgSummary>().lambda().eq(TEOrgSummary::getOrgId, orgId));
    }

    /**
     * 删除机构统计缓存
     *
     * @param orgId
     */
    @Override
    @CacheEvict(value = SystemConstant.orgSummaryCache, key = "#p0")
    public void removeOrgSummaryCache(Long orgId) {

    }

    /**
     * 获取地区统计缓存
     *
     * @return
     */
    @Override
    @Cacheable(value = SystemConstant.regionSummaryCache, unless = "#result?.size() == 0")
    public List<TERegionSummary> getRegionSummaryCache() {
        return teRegionSummaryService.list();
    }

    /**
     * 更新地区统计缓存
     *
     * @return
     */
    @Override
    @CachePut(value = SystemConstant.regionSummaryCache, condition = "#result?.size() > 0")
    public List<TERegionSummary> updateRegionSummaryCache() {
        return teRegionSummaryService.list();
    }

    /**
     * 删除地区统计缓存
     */
    @Override
    @CacheEvict(value = SystemConstant.regionSummaryCache)
    public void removeOrgSummaryCache() {

    }

    /**
     * 删除全部考试统计缓存
     *
     * @param examId
     * @param examActivityId
     * @param roomCode
     */
    @Override
    public void removeExamSummaryAllCache(Long examId, Long examActivityId, String roomCode) {
        this.removeExamSummaryCache(examId);
        this.removeExamSummaryCache(examId, examActivityId);
        this.removeExamSummaryCache(examId, examActivityId, roomCode);
    }

    /**
     * 考试记录改变cache
     *
     * @param key
     * @param timestamp
     */
    @Override
    public void addExamRecordChangeCache(String key, Long timestamp) {
        redisUtil.setZset(key, key, timestamp);
    }

    /**
     * 获取考试记录score
     *
     * @param key
     * @return
     */
    @Override
    public Long getExamRecordChangeCache(String key) {
        Double d = redisUtil.getZset(key, key);
        return Objects.nonNull(d) ? d.longValue() : null;
    }
}
