package com.qmth.teachcloud.common.service.impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import com.qmth.boot.core.enums.Platform;
import com.qmth.teachcloud.common.bean.auth.AuthBean;
import com.qmth.teachcloud.common.bean.auth.ExpireTimeBean;
import com.qmth.teachcloud.common.bean.dto.MenuDto;
import com.qmth.teachcloud.common.bean.dto.MenuPrivilegeDto;
import com.qmth.teachcloud.common.bean.dto.OrgDto;
import com.qmth.teachcloud.common.bean.result.*;
import com.qmth.teachcloud.common.bean.vo.FilePathVo;
import com.qmth.teachcloud.common.config.DictionaryConfig;
import com.qmth.teachcloud.common.contant.SpringContextHolder;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.entity.*;
import com.qmth.teachcloud.common.enums.*;
import com.qmth.teachcloud.common.service.*;
import com.qmth.teachcloud.common.util.*;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.LinkedMultiValueMap;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 公共服务service impl
 * @Param:
 * @return:
 * @Author: wangliang
 * @Date: 2021/3/26
 */
@Service
public class TeachcloudCommonServiceImpl implements TeachcloudCommonService {
    private final static Logger log = LoggerFactory.getLogger(TeachcloudCommonServiceImpl.class);

    @Resource
    CommonCacheService commonCacheService;

    @Resource
    SysUserRoleService sysUserRoleService;

    @Resource
    SysPrivilegeService sysPrivilegeService;

    @Resource
    SysRolePrivilegeService sysRolePrivilegeService;

    @Resource
    SysRoleService sysRoleService;

    @Resource
    TBSessionService tbSessionService;

    @Resource
    RedisUtil redisUtil;

    @Resource
    DictionaryConfig dictionaryConfig;

//    @Resource
//    OssUtil ossUtil;

    @Autowired
    private SysOrgService sysOrgService;

    @Resource
    TeachcloudCommonService commonService;

    @Resource
    BasicAttachmentService basicAttachmentService;

    @Resource
    FileStoreUtil fileStoreUtil;

    @Resource
    SysUserService sysUserService;

    @Resource
    ConvertUtil convertUtil;

    @Resource
    BasicCampusService basicCampusService;

    @Resource
    BasicCourseService basicCourseService;

    @Resource
    RedisCounterUtil redisCounterUtil;

    /**
     * 获取用户菜单
     *
     * @param userId
     * @return
     */
    @Override
    public MenuResult getUserMenu(Long userId) {
        SysUser sysUser = commonCacheService.userCache(userId);
        List<SysUserRole> sysUserRoleList = commonCacheService.userRolePrivilegeCache(userId);
        List<SysRolePrivilege> sysRolePrivilegeList = new ArrayList<>();
        for (SysUserRole s : sysUserRoleList) {
            SysRole sysRole = commonCacheService.roleCache(s.getRoleId());
            if (Objects.nonNull(sysRole) && sysRole.getEnable()) {
                sysRolePrivilegeList.addAll(commonCacheService.rolePrivilegeCache(sysUser.getSchoolId(), s.getRoleId()));
            }
        }
        Set<Long> privilegeIds = sysRolePrivilegeList.stream().map(s -> s.getPrivilegeId()).collect(Collectors.toSet());
        QueryWrapper<SysPrivilege> sysPrivilegeQueryWrapper = new QueryWrapper<>();
        sysPrivilegeQueryWrapper.lambda()
                .eq(SysPrivilege::getEnable, true).eq(SysPrivilege::getFrontDisplay, true)
                .orderByAsc(SysPrivilege::getSequence);

        if (!privilegeIds.isEmpty()) {
            sysPrivilegeQueryWrapper.lambda().in(SysPrivilege::getId, privilegeIds);
        }
        List<SysPrivilege> sysPrivilegeList = sysPrivilegeService.list(sysPrivilegeQueryWrapper);
        Gson gson = new Gson();
        List<MenuDto> menuDtoList = gson.fromJson(JacksonUtil.parseJson(sysPrivilegeList), new TypeToken<List<MenuDto>>() {
        }.getType());
        LinkedMultiValueMap<Long, MenuDto> linkedMultiValueMap = new LinkedMultiValueMap<>();
        List<MenuPrivilegeDto> menuPrivilegeDtoList = new ArrayList<>();
        for (MenuDto m : menuDtoList) {
            if (Objects.isNull(m.getParentId()) || m.getType() == PrivilegeEnum.MENU) {
                menuPrivilegeDtoList.add(gson.fromJson(gson.toJson(m), MenuPrivilegeDto.class));
            } else {
                if (!linkedMultiValueMap.containsKey(m.getParentId())) {
                    linkedMultiValueMap.add(m.getParentId(), m);
                } else {
                    List<MenuDto> menuDtos = linkedMultiValueMap.get(m.getParentId());
                    menuDtos.add(m);
                    linkedMultiValueMap.put(m.getParentId(), menuDtos);
                }
            }
        }
        for (MenuPrivilegeDto m : menuPrivilegeDtoList) {
            List<MenuDto> menuDtos = linkedMultiValueMap.get(m.getId());
            List<MenuDto> urls = null, buttons = null, links = null, lists = null, conditions = null;
            if (Objects.nonNull(menuDtos)) {
                for (MenuDto menuDto : menuDtos) {
                    if (menuDto.getType() == PrivilegeEnum.BUTTON) {
                        buttons = Objects.isNull(buttons) ? new ArrayList<>() : buttons;
                        buttons.add(gson.fromJson(gson.toJson(menuDto), MenuPrivilegeDto.class));
                        m.setButtons(buttons);
                    } else if (menuDto.getType() == PrivilegeEnum.LINK) {
                        links = Objects.isNull(links) ? new ArrayList<>() : links;
                        links.add(gson.fromJson(gson.toJson(menuDto), MenuPrivilegeDto.class));
                        m.setLinks(links);
                    } else if (menuDto.getType() == PrivilegeEnum.URL) {
                        urls = Objects.isNull(urls) ? new ArrayList<>() : urls;
                        urls.add(gson.fromJson(gson.toJson(menuDto), MenuPrivilegeDto.class));
                        m.setUrls(urls);
                    } else if (menuDto.getType() == PrivilegeEnum.LIST) {
                        lists = Objects.isNull(lists) ? new ArrayList<>() : lists;
                        lists.add(gson.fromJson(gson.toJson(menuDto), MenuPrivilegeDto.class));
                        m.setLists(lists);
                    } else if (menuDto.getType() == PrivilegeEnum.CONDITION) {
                        conditions = Objects.isNull(conditions) ? new ArrayList<>() : conditions;
                        conditions.add(gson.fromJson(gson.toJson(menuDto), MenuPrivilegeDto.class));
                        m.setConditions(conditions);
                    }
                }
            }
        }
        return new MenuResult(sysUser.getId(), menuPrivilegeDtoList);
    }

    /**
     * 新增用户权限
     *
     * @param sysUser
     * @param roleId
     */
    @Override
    public void addUserRolePrivilege(SysUser sysUser, Long roleId) {
        List<SysRolePrivilege> sysRolePrivilegeList = commonCacheService.rolePrivilegeCache(sysUser.getSchoolId(), roleId);
        List<SysUserRole> sysUserRoleList = new ArrayList<>();
        sysRolePrivilegeList.forEach(s -> {
            sysUserRoleList.add(new SysUserRole(sysUser.getId(), s.getRoleId(), s.getPrivilegeId()));
        });
        sysUserRoleService.saveBatch(sysUserRoleList);
    }

    /**
     * 新增用户权限
     *
     * @param sysUser
     * @param roleIds
     */
    @Override
    public void addUserRolePrivilege(SysUser sysUser, Long[] roleIds) {
        List<SysUserRole> sysUserRoleList = new ArrayList<>();
        for (int i = 0; i < roleIds.length; i++) {
            sysUserRoleList.add(new SysUserRole(sysUser.getId(), roleIds[i]));
        }
        sysUserRoleService.saveBatch(sysUserRoleList);
    }

    @Override
    public List<SysUserRole> disposeUserPrivilege(SysUser sysUser, Long[] roleIds) {
        List<SysUserRole> sysUserRoleList = new ArrayList<>();
        for (int i = 0; i < roleIds.length; i++) {
            sysUserRoleList.add(new SysUserRole(sysUser.getId(), roleIds[i]));
        }
        return sysUserRoleList;
    }


    /**
     * 获取用户角色权限
     *
     * @param userId
     * @return
     */
    @Override
    public List<SysUserRole> getUserRolePrivilege(Long userId) {
        QueryWrapper<SysUserRole> sysUserRoleQueryWrapper = new QueryWrapper<>();
        sysUserRoleQueryWrapper.lambda().eq(SysUserRole::getUserId, userId)
                .eq(SysUserRole::getEnable, true);
        return sysUserRoleService.list(sysUserRoleQueryWrapper);
    }

    /**
     * 获取角色权限
     *
     * @param roleId
     * @return
     */
    @Override
    public List<SysRolePrivilege> getRolePrivilege(Long schoolId, Long roleId) {
        QueryWrapper<SysRolePrivilege> sysRolePrivilegeQueryWrapper = new QueryWrapper<>();
        sysRolePrivilegeQueryWrapper.lambda().eq(SysRolePrivilege::getRoleId, roleId);
        if (schoolId == null) {
            sysRolePrivilegeQueryWrapper.lambda().isNull(SysRolePrivilege::getSchoolId);
        } else {
            sysRolePrivilegeQueryWrapper.lambda().and(t -> t.isNull(SysRolePrivilege::getSchoolId).or().eq(SysRolePrivilege::getSchoolId, schoolId));
        }
        return sysRolePrivilegeService.list(sysRolePrivilegeQueryWrapper);
    }

    /**
     * 获取用户权限
     *
     * @param userId
     * @return
     */
    @Override
    public AuthBean getUserAuth(Long userId) {
        AuthBean authBean = null;
        try {
            CommonCacheService commonCacheService = SpringContextHolder.getBean(CommonCacheService.class);
            SysUser user = commonCacheService.userCache(userId);
            if (Objects.isNull(user)) {
                throw ExceptionResultEnum.USER_NO_DATA.exception();
            }
            //查询用户角色和权限
            List<SysUserRole> sysUserRoleList = commonCacheService.userRolePrivilegeCache(user.getId());
            if (Objects.nonNull(sysUserRoleList) && sysUserRoleList.size() > 0) {
                Set<Long> roleIds = sysUserRoleList.stream().map(s -> s.getRoleId()).collect(Collectors.toSet());
                List<SysRolePrivilege> sysRolePrivilegeList = new ArrayList<>();
                for (Long l : roleIds) {
                    sysRolePrivilegeList.addAll(commonCacheService.rolePrivilegeCache(user.getSchoolId(), l));
                }
                Set<Long> privilegeIds = sysRolePrivilegeList.stream().map(s -> s.getPrivilegeId()).collect(Collectors.toSet());
                QueryWrapper<SysRole> sysRoleQueryWrapper = new QueryWrapper<>();
                sysRoleQueryWrapper.lambda().in(SysRole::getId, roleIds)
                        .eq(SysRole::getEnable, true);
                List<SysRole> sysRoleList = sysRoleService.list(sysRoleQueryWrapper);
                int count = Objects.nonNull(sysRoleList) && sysRoleList.size() > 0 ? (int) sysRoleList.stream().filter(s -> Objects.equals(s.getName(), RoleTypeEnum.ADMIN.getName())).count() : 0;
                QueryWrapper<SysPrivilege> sysPrivilegeQueryWrapper = new QueryWrapper<>();
                if (count > 0) {//超级系统管理员
//                    Long schoolId = Long.parseLong(ServletUtil.getRequestSchoolByNotVaild().toString());
                    sysPrivilegeQueryWrapper.lambda()
//                            .eq(SysPrivilege::getSchoolId, schoolId)
                            .eq(SysPrivilege::getType, PrivilegeEnum.URL)
                            .eq(SysPrivilege::getProperty, PrivilegePropertyEnum.AUTH);
                    List<SysPrivilege> sysPrivilegeList = sysPrivilegeService.list(sysPrivilegeQueryWrapper);
                    authBean = new AuthBean(sysRoleList, sysPrivilegeList.stream().map(s -> s.getUrl()).collect(Collectors.toSet()));
                } else {
                    BasicSchool tbSchool = Objects.nonNull(user.getSchoolId()) ? commonCacheService.schoolCache(user.getSchoolId()) : null;
                    SysOrg org = Objects.nonNull(user.getOrgId()) ? commonCacheService.orgCache(user.getOrgId()) : null;
                    List<SysPrivilege> sysPrivilegeList = new ArrayList<>();
                    if (privilegeIds.size() > 0) {
                        sysPrivilegeQueryWrapper.lambda().in(SysPrivilege::getId, privilegeIds)
                                .eq(SysPrivilege::getType, PrivilegeEnum.URL)
                                .eq(SysPrivilege::getProperty, PrivilegePropertyEnum.AUTH);
                        sysPrivilegeList = sysPrivilegeService.list(sysPrivilegeQueryWrapper);
                    }
//                    if (Objects.isNull(tbSchool)) {
//                        sysPrivilegeQueryWrapper.lambda().isNull(SysPrivilege::getSchoolId);
//                    } else {
//                        sysPrivilegeQueryWrapper.lambda().eq(SysPrivilege::getSchoolId, user.getSchoolId());
//                    }
                    authBean = new AuthBean(sysRoleList, sysPrivilegeList.stream().map(s -> s.getUrl()).collect(Collectors.toSet()), tbSchool, org);
                }
            }
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
            throw ExceptionResultEnum.ERROR.exception("添加用户鉴权缓存失败");
        }
        return authBean;
    }

    /**
     * 获取鉴权url
     *
     * @param privilegePropertyEnum
     * @return
     */
    @Override
    public Set<String> getPrivilegeUrl(PrivilegePropertyEnum privilegePropertyEnum) {
        QueryWrapper<SysPrivilege> sysPrivilegeQueryWrapper = new QueryWrapper<>();
        sysPrivilegeQueryWrapper.lambda().eq(SysPrivilege::getType, PrivilegeEnum.URL)
                .eq(SysPrivilege::getProperty, privilegePropertyEnum)
                .eq(SysPrivilege::getEnable, true);
        List<SysPrivilege> sysPrivilegeList = sysPrivilegeService.list(sysPrivilegeQueryWrapper);
        return Objects.nonNull(sysPrivilegeList) && sysPrivilegeList.size() > 0 ? sysPrivilegeList.stream().map(s -> s.getUrl()).collect(Collectors.toSet()) : null;
    }

    /**
     * 获取鉴权url
     *
     * @param privilegePropertyEnum
     * @param schoolId
     * @return
     */
    @Override
    public Set<String> getPrivilegeUrl(PrivilegePropertyEnum privilegePropertyEnum, Long schoolId) {
        QueryWrapper<SysPrivilege> sysPrivilegeQueryWrapper = new QueryWrapper<>();
        sysPrivilegeQueryWrapper.lambda().eq(SysPrivilege::getType, PrivilegeEnum.URL)
                .eq(SysPrivilege::getProperty, privilegePropertyEnum)
                .eq(SysPrivilege::getEnable, true)
                .eq(SysPrivilege::getDefaultAuth, true);
//                .eq(SysPrivilege::getSchoolId, schoolId);
        List<SysPrivilege> sysPrivilegeList = sysPrivilegeService.list(sysPrivilegeQueryWrapper);
        return Objects.nonNull(sysPrivilegeList) && sysPrivilegeList.size() > 0 ? sysPrivilegeList.stream().map(s -> s.getUrl()).collect(Collectors.toSet()) : null;
    }

    /**
     * 删除用户信息
     *
     * @param userId
     * @param all
     */
    @Override
    public void removeUserInfo(Long userId, boolean all) throws NoSuchAlgorithmException {
        AuthBean authBean = commonCacheService.userAuthCache(userId);
        if (Objects.isNull(authBean)) {
            throw ExceptionResultEnum.NOT_LOGIN.exception();
        }
        if (all) {
            for (Platform p : Platform.values()) {
                Set<String> roleNamesSet = authBean.getRoleList().stream().map(s -> s.getName()).collect(Collectors.toSet());
                List<String> roleNames = new ArrayList<>();
                roleNames.addAll(roleNamesSet);
                Collections.sort(roleNames);
                String sessionId = SessionUtil.digest(userId, Math.abs(roleNames.toString().hashCode()), p.name());
                tbSessionService.removeById(sessionId);
                redisUtil.deleteUserSession(sessionId);
            }
        } else {
            Set<String> roleNamesSet = authBean.getRoleList().stream().map(s -> s.getName()).collect(Collectors.toSet());
            List<String> roleNames = new ArrayList<>();
            roleNames.addAll(roleNamesSet);
            Collections.sort(roleNames);
            String sessionId = SessionUtil.digest(userId, Math.abs(roleNames.toString().hashCode()), Platform.WEB.name());
            tbSessionService.removeById(sessionId);
            redisUtil.deleteUserSession(sessionId);
        }
        SystemConstant.deleteUserCache(userId);
    }

    /**
     * 批量删除用户信息
     *
     * @param userIds
     * @param all
     */
    @Override
    public void removeUserInfoBatch(List<Long> userIds, boolean all) {
        if (!CollectionUtils.isEmpty(userIds)) {
            new Thread(() -> {
                if (all) {
                    Set<String> sessionIdSet = new HashSet<>(Platform.values().length * userIds.size());
                    int min = 0;
                    int max = SystemConstant.IN_SIZE_MAX, size = userIds.size();
                    if (max >= size) {
                        max = size;
                    }
                    while (max <= size) {
                        List<UserRoleNameResult> userRoleNameResultList = sysUserService.selectRoleNames(userIds.subList(min, max));
                        for (UserRoleNameResult userRoleNameResult : userRoleNameResultList) {
                            List<String> roleNames = Arrays.asList(userRoleNameResult.getRoleNames().split(","));
                            Collections.sort(roleNames);
                            for (Platform p : Platform.values()) {
                                String sessionId = null;
                                try {
                                    sessionId = SessionUtil.digest(userRoleNameResult.getUserId(), Math.abs(roleNames.toString().hashCode()), p.name());
                                } catch (NoSuchAlgorithmException e) {
                                    e.printStackTrace();
                                }
                                sessionIdSet.add(sessionId);
                            }
                        }
                        if (max == size) {
                            break;
                        }
                        min = max;
                        max += SystemConstant.IN_SIZE_MAX;
                        if (max >= size) {
                            max = size;
                        }
                    }
                    tbSessionService.removeByIds(sessionIdSet);
                    for (String s : sessionIdSet) {
                        redisUtil.deleteUserSession(s);
                    }
                } else {
                    TBSession tbSession = (TBSession) ServletUtil.getRequestSession();
                    tbSessionService.removeById(tbSession.getId());
                    redisUtil.deleteUserSession(tbSession.getId());
                }
                for (Long l : userIds) {
                    SystemConstant.deleteUserCache(l);
                }
            }).start();
        }
    }

    /**
     * 文件预览
     *
     * @param path
     * @return
     */
    @Override
    public String filePreview(String path) {
        if (StringUtils.isBlank(path)) {
            return null;
        }
        String url = null;
        JSONObject jsonObject = JSONObject.parseObject(path);
        String attachmentType = (String) jsonObject.get(SystemConstant.TYPE);
        String filePath = (String) jsonObject.get(SystemConstant.PATH);
        if (Objects.equals(attachmentType, SystemConstant.LOCAL)) {
            if (filePath.contains(dictionaryConfig.fssPrivateDomain().getServer())) {
                url = filePath.substring(filePath.indexOf(dictionaryConfig.fssPrivateDomain().getServer()), filePath.length());
            } else if (filePath.contains(dictionaryConfig.fssPublicDomain().getServer())) {
                url = filePath.substring(filePath.indexOf(dictionaryConfig.fssPublicDomain().getServer()), filePath.length());
            } else {
                UploadFileEnum uploadFileEnum = UploadFileEnum.valueOf((String) jsonObject.get(SystemConstant.UPLOAD_TYPE));
                url = fileStoreUtil.getPrivateUrl(filePath, uploadFileEnum.getFssType());
            }
        } else {
            UploadFileEnum uploadFileEnum = UploadFileEnum.valueOf((String) jsonObject.get(SystemConstant.UPLOAD_TYPE));
            url = fileStoreUtil.getPrivateUrl(filePath, uploadFileEnum.getFssType());
        }
        return FileUtil.replaceSplit(url);
    }

    /**
     * 文件预览
     *
     * @param attachmentId
     * @return
     */
    @Override
    public String filePreview(Long attachmentId) {
        BasicAttachment basicAttachment = basicAttachmentService.getById(attachmentId);
        if (basicAttachment == null) {
            return null;
        }
        return filePreview(basicAttachment.getPath());
    }

    /**
     * 文件预览
     *
     * @param path     附件路径
     * @param type     保存类型：本地、OSS
     * @param isExpire url是否带过期时间
     * @return
     */
    @Override
    public String filePreviewByPathAndType(String path, String uploadType, String type, Boolean isExpire) {
        if (StringUtils.isBlank(path)) {
            return null;
        }
        String pathUrl;
        if (Objects.equals(type, SystemConstant.LOCAL)) {
            if (path.contains(dictionaryConfig.fssPrivateDomain().getServer())) {
                pathUrl = path.substring(path.indexOf(dictionaryConfig.fssPrivateDomain().getServer()), path.length());
            } else if (path.contains(dictionaryConfig.fssPublicDomain().getServer())) {
                pathUrl = path.substring(path.indexOf(dictionaryConfig.fssPublicDomain().getServer()), path.length());
            } else {
                UploadFileEnum uploadFileEnum = UploadFileEnum.valueOf(uploadType);
                pathUrl = fileStoreUtil.getPrivateUrl(path, uploadFileEnum.getFssType());
            }
        } else {
            pathUrl = fileStoreUtil.getPrivateUrl(path, fileStoreUtil.getUploadEnumByPath(path).getFssType());
        }
        return pathUrl;
    }

    /**
     * 文件预览
     *
     * @param attachmentId 附件路径
     * @param isExpire     url是否带过期时间
     * @return
     */
    @Override
    public Map<String, String> filePreviewByAttachmentId(Long attachmentId, Boolean isExpire) {
        BasicAttachment attachment = basicAttachmentService.getById(attachmentId);
        if (attachment == null) {
            return null;
        }

        Map<String, String> map = new HashMap<>();

        String pathUrl;
        JSONObject jsonObject = JSONObject.parseObject(attachment.getPath());
        String attachmentType = (String) jsonObject.get(SystemConstant.TYPE);
        String filePath = (String) jsonObject.get(SystemConstant.PATH);
        UploadFileEnum uploadFileEnum = jsonObject.get(SystemConstant.UPLOAD_TYPE).toString().contains(UploadFileEnum.HTML.name()) ? UploadFileEnum.HTML : UploadFileEnum.valueOf((String) jsonObject.get(SystemConstant.UPLOAD_TYPE));

        if (Objects.equals(attachmentType, SystemConstant.LOCAL)) {
            if (filePath.contains(dictionaryConfig.fssPrivateDomain().getServer())) {
                pathUrl = filePath.substring(filePath.indexOf(dictionaryConfig.fssPrivateDomain().getServer()), filePath.length());
            } else if (filePath.contains(dictionaryConfig.fssPublicDomain().getServer())) {
                pathUrl = filePath.substring(filePath.indexOf(dictionaryConfig.fssPublicDomain().getServer()), filePath.length());
            } else {
                pathUrl = fileStoreUtil.getPrivateUrl(filePath, uploadFileEnum.getFssType());
            }
        } else {
            pathUrl = fileStoreUtil.getPrivateUrlExpire(filePath, uploadFileEnum.getFssType(), isExpire);
        }
        map.put("url", pathUrl);
        if (attachment.getType().equals(SystemConstant.HTML_PREFIX)) {
            String htmlMd5 = (String) jsonObject.get("htmlMd5");
            map.put("md5", htmlMd5);
        } else {
            map.put("md5", attachment.getMd5());
        }
        return map;
    }

    @Override
    public String readFileContent(String path) {
        // 解析path
        JSONObject object = JSONObject.parseObject(path);
        String filePath = object.getString(SystemConstant.PATH);
        String type = object.getString(SystemConstant.TYPE);
        UploadFileEnum uploadType = Enum.valueOf(UploadFileEnum.class, (String) object.get(SystemConstant.UPLOAD_TYPE));

        if (filePath.endsWith(SystemConstant.HTML_PREFIX) || filePath.endsWith(SystemConstant.FTL_PREFIX)) {
            StringBuffer sb = new StringBuffer();
            File fileTemp = null;
            InputStream fis = null;
            try {
                fileTemp = SystemConstant.getFileTempVar(SystemConstant.HTML_PREFIX);
                if (type.equals(SystemConstant.OSS)) {
                    fis = fileStoreUtil.ossDownloadIs(filePath, uploadType.getFssType());
                    FileUtils.copyInputStreamToFile(fis, fileTemp);
                } else {
                    File file = null;
                    if (dictionaryConfig.fssPrivateDomain().getConfig().startsWith(SystemConstant.START_PARENT) || dictionaryConfig.fssPublicDomain().getConfig().startsWith(SystemConstant.START_PARENT)) {
                        file = new File(dictionaryConfig.fssPublicDomain().getConfig(), filePath);
                    } else {
                        file = new File(filePath);
                    }
                    FileCopyUtils.copy(file, fileTemp);
                }
                if (Objects.nonNull(fileTemp)) {
                    sb.append(FileUtils.readFileToString(fileTemp, StandardCharsets.UTF_8));
                }
            } catch (Exception e) {
                log.error(SystemConstant.LOG_ERROR, e);
            } finally {
                if (Objects.nonNull(fis)) {
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (Objects.nonNull(fileTemp)) {
                    fileTemp.delete();
                }
            }
            return sb.toString();
        }
        return null;
    }

    /**
     * 获取文件
     *
     * @param path
     * @param pdf
     * @param fileTempList
     * @return
     * @throws IOException
     */
    @Override
    public File getFile(String path, boolean pdf, List<File> fileTempList) throws Exception {
        File file = null;
        JSONObject jsonObject = JSONObject.parseObject(path);
        String attachmentType = (String) jsonObject.get(SystemConstant.TYPE);
        String filePath = pdf ? (String) jsonObject.get(SystemConstant.PDF_PATH) : (String) jsonObject.get(SystemConstant.PATH);
        Optional.ofNullable(filePath).orElseThrow(() -> ExceptionResultEnum.ATTACHMENT_IS_NULL.exception("附件路径不存在"));

        UploadFileEnum uploadType = Enum.valueOf(UploadFileEnum.class, (String) jsonObject.get(SystemConstant.UPLOAD_TYPE));
        if (Objects.equals(attachmentType, SystemConstant.OSS)) {
            String suffix = filePath.substring(filePath.lastIndexOf(".")).toLowerCase();
            File fileTemp = SystemConstant.getFileTempVar(suffix);
            fileTempList.add(fileTemp);
            file = fileStoreUtil.ossDownload(filePath, fileTemp, uploadType.getFssType());
        } else {
            if (dictionaryConfig.fssPrivateDomain().getConfig().startsWith(SystemConstant.START_PARENT) || dictionaryConfig.fssPublicDomain().getConfig().startsWith(SystemConstant.START_PARENT)) {
                file = new File(dictionaryConfig.fssPrivateDomain().getConfig(), filePath);
            } else {
                file = new File(filePath);
            }
        }
        return file;
    }

    @Override
    public Set<Long> listSubOrgIds(Long id) {
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        Long orgId;
        if (id == null) {
            orgId = sysUser.getOrgId();
        } else {
            orgId = id;
        }
        if (orgId == null) {
            return null;
        }
        List<OrgDto> orgDtos = sysOrgService.listOrgTree(null, false, null, null);
        Set<Long> stringSet = new HashSet<>();
        stringSet.add(orgId);
        stringSet = getOrgIds(stringSet, orgDtos, orgId);
        return stringSet;
    }

    /**
     * 登录公用
     *
     * @param password
     * @param sysUser
     * @param appSource
     * @return
     * @throws NoSuchAlgorithmException
     */
    @Override
    public LoginResult login(String password, SysUser sysUser, AppSourceEnum appSource) throws NoSuchAlgorithmException {
        //停用
        if (!sysUser.getEnable()) {
            throw ExceptionResultEnum.USER_ENABLE.exception();
        }

        Platform platform = ServletUtil.getRequestPlatform();
        String deviceId = ServletUtil.getRequestDeviceId();
        AuthBean authBean = commonService.getUserAuth(sysUser.getId());
        //添加用户鉴权缓存
        if (Objects.isNull(authBean)) {
            throw ExceptionResultEnum.ROLE_ENABLE_AUTHORIZATION.exception();
        }
        //生成token
        String token = SystemConstant.getNanoId();
        commonCacheService.userCache(sysUser.getId());
        //添加用户会话缓存
        Set<String> roleNamesSet = new HashSet<>(), roleTypes = new HashSet<>(), role = new HashSet<>();
        List<RoleResult> roleSource = new ArrayList<>();
        for (SysRole s : authBean.getRoleList()) {
            roleNamesSet.add(s.getName());
            if (s.getType() != null) {
                role.add(s.getType().name());
            }
            if (Objects.isNull(s.getSource()) && Objects.nonNull(s.getType())) {
                roleTypes.add(s.getType().name());
            }
            roleSource.add(Objects.nonNull(s.getType()) ? new RoleResult(s.getId(), s.getName(), s.getType().name(), s.getSource()) : new RoleResult(s.getId(), s.getName(), s.getSource()));
        }
        List<String> roleNames = new ArrayList<>();
        roleNames.addAll(roleNamesSet);
        Collections.sort(roleNames);
        String sessionId = SessionUtil.digest(sysUser.getId(), Math.abs(roleNames.toString().hashCode()), platform.name());
        //TODO 测试用
//        String test = SignatureEntityTest.build(SignatureType.TOKEN, sessionId, token);
        ExpireTimeBean expireTime = AuthUtil.getExpireTime(platform);
        TBSession tbSession = new TBSession(sysUser.getSchoolId(), sessionId, String.valueOf(sysUser.getId()), roleNames.toString(),
                platform.name(), platform.name(), deviceId, ServletUtil.getRequest().getLocalAddr(), token,
                expireTime.getDate().getTime(), appSource);
        tbSessionService.saveOrUpdate(tbSession);
        redisUtil.setUserSession(sessionId, tbSession, expireTime.getExpireSeconds());

//        LoginResult loginResult = new LoginResult(sysUser, sessionId, test, Objects.nonNull(roleTypes) && roleTypes.size() > 0 ? roleTypes : roleNamesSet, appSource, roleSource);
        LoginResult loginResult = new LoginResult(sysUser, sessionId, token, Objects.nonNull(roleTypes) && roleTypes.size() > 0 ? roleTypes : roleNamesSet, appSource, roleSource, SystemConstant.VERSION_VALUE);
        loginResult.setSchoolInfo(Objects.nonNull(authBean.getSchool()) ? Lists.newArrayList(loginResult.new SchoolNativeBean(authBean.getSchool())) : null);
        loginResult.setOrgInfo(Objects.nonNull(authBean.getOrg()) ? loginResult.new OrgNativeBean(authBean.getOrg()) : null);
        loginResult.setRole(role);
        loginResult.setTime(System.currentTimeMillis());
        String mobileNumber = sysUser.getMobileNumber();
        int pwdCount = sysUser.getPwdCount();
        if (roleTypes.contains(RoleTypeEnum.ADMIN.name())) {
            mobileNumber = sysUser.getLoginName() + "（特殊权限）";
            pwdCount = 1;
        }
        loginResult.setUserLoginCheckResult(new UserLoginCheckResult(sysUser.getId(), mobileNumber, pwdCount));
//        //TODO 西交大切换学校定制
//        QueryWrapper<SysUser> sysUserQueryWrapper = new QueryWrapper<>();
//        sysUserQueryWrapper.lambda().eq(SysUser::getLoginName, sysUser.getLoginName())
//                .eq(SysUser::getEnable, true);
//        List<SysUser> sysUserList = sysUserService.list(sysUserQueryWrapper);
//        if (sysUserList.size() > 1) {
//            List<LoginResult.SchoolNativeBean> schoolNativeBeanList = new ArrayList<>(sysUserList.size());
//            for (SysUser s : sysUserList) {
//                BasicSchool school = commonCacheService.schoolCache(s.getSchoolId());
//                schoolNativeBeanList.add(loginResult.new SchoolNativeBean(school, s.getPassword()));
//            }
//            loginResult.setSchoolInfo(schoolNativeBeanList);
//        }
        return loginResult;
    }

    @Override
    public String getSysIncrCode(SystemCodeEnum type, SysUser requestUser) {
        Long schoolId = requestUser.getSchoolId();
        String date = DateUtil.today().replace(SystemConstant.HYPHEN, "");
        int count = 0;
        String code = date.concat(redisCounterUtil.getCounter(schoolId, 4, type.getCode()));
        do {
            switch (type) {
                case CAMPUS_CODE:
                    count = basicCampusService.count(new QueryWrapper<BasicCampus>().lambda()
                            .eq(BasicCampus::getCampusCode, code)
                            .eq(BasicCampus::getSchoolId, schoolId));
                    break;
                case COURSE_CODE:
                    count = basicCourseService.count(new QueryWrapper<BasicCourse>().lambda()
                            .eq(BasicCourse::getCode, code)
                            .eq(BasicCourse::getSchoolId, schoolId));
                    break;
                default:
                    break;
            }
        } while (count > 0);
        return code;
    }

    @Override
    public boolean containsPrivilege(Long userId, String button, String selectStudent) {
        MenuResult menuResult = commonCacheService.userMenuCache(userId);
        if (menuResult != null && !CollectionUtils.isEmpty(menuResult.getPrivileges())) {
            List<MenuPrivilegeDto> menuResultPrivileges = menuResult.getPrivileges();
            long count = 0;
            for (MenuPrivilegeDto menuResultPrivilege : menuResultPrivileges) {
                List<MenuDto> menuDtoList = "button".equals(button) ? menuResultPrivilege.getButtons() : "link".equals(button) ? menuResultPrivilege.getLinks() : null;
                if (!CollectionUtils.isEmpty(menuDtoList)) {
                    long filterCount = menuDtoList.stream().filter(m -> m.getUrl().equalsIgnoreCase(selectStudent)).count();
                    count = count + filterCount;
                }
            }
            return count > 0;
        }
        return false;
    }

    private Set<Long> getOrgIds(Set<Long> stringSet, List<OrgDto> orgDtos, Long parentId) {
        for (OrgDto orgDto : orgDtos) {
            Long tempParentId = orgDto.getParentId();
            if (parentId.equals(tempParentId) && stringSet.contains(parentId)) {
                stringSet.add(Long.valueOf(orgDto.getId()));
            }
            if (orgDto.getChildren().isEmpty()) {
                continue;
            }
            getOrgIds(stringSet, orgDto.getChildren(), Long.valueOf(orgDto.getId()));
        }
        return stringSet;
    }

    @Override
    public List<String> filePreview(List<String> paths) {
        List<String> result = new ArrayList<String>();
        for (String path : paths) {
            result.add(this.filePreview(path));
        }
        return result;
    }

    @Override
    public List<String> fileMarkPreview(List<String> paths) {
        List<String> result = new ArrayList<>();
        for (String path : paths) {
            FilePathVo filePathVo = JSON.parseObject(path, FilePathVo.class);
            String pathVoPath = filePathVo.getPath();
            if (SystemConstant.LOCAL.equals(filePathVo.getType())) {
                result.add(!pathVoPath.startsWith(SystemConstant.ORG_SPLIT) ? SystemConstant.ORG_SPLIT + pathVoPath : pathVoPath);
            } else {
                result.add(this.filePreview(path));
            }
        }
        return result;
    }
}
