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

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.gson.Gson;
import com.qmth.boot.core.solar.model.AppInfo;
import com.qmth.boot.core.solar.model.OrgInfo;
import com.qmth.boot.core.solar.service.SolarService;
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.AuthOrgInfoDto;
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.common.enums.ExceptionResultEnum;
import com.qmth.themis.common.exception.BusinessException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

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

    @Resource
    TBUserRoleService tbUserRoleService;

    @Resource
    TBPrivilegeService tbPrivilegeService;

    @Resource
    TBRolePrivilegeService tbRolePrivilegeService;

    @Resource
    TBUserService tbUserService;

    @Resource
    TBOrgService tbOrgService;

    @Resource
    TEStudentService teStudentService;

    @Resource
    SysConfigService sysConfigService;

    @Resource
    SolarService solarService;

    @Resource
    TEAudioService teAudioService;

    @Resource
    TBAttachmentService tbAttachmentService;

    /**
     * 添加机构缓存
     *
     * @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));
        if (Objects.isNull(tbOrg)) {
            throw 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 {
            CacheService cacheService = SpringContextHolder.getBean(CacheService.class);
            TBUser user = cacheService.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()) ? cacheService.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 {
            CacheService cacheService = SpringContextHolder.getBean(CacheService.class);
            TEStudentCacheDto teStudentCacheDto = cacheService.addStudentAccountCache(studentId);
            if (Objects.isNull(teStudentCacheDto)) {
                throw new BusinessException(ExceptionResultEnum.STUDENT_NO);
            }
            TBOrg tbOrg = cacheService.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);
        Gson gson = new Gson();
        return gson.fromJson(gson.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);
        Gson gson = new Gson();
        return gson.fromJson(gson.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.getById(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) {

    }
}
