package jnpf.doclibrary.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.xuyanwu.spring.file.storage.FileInfo;
import cn.xuyanwu.spring.file.storage.MockMultipartFile;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import jnpf.base.ActionResult;
import jnpf.base.UserInfo;
import jnpf.doclibrary.mapper.InformationAuthorityMapper;
import jnpf.doclibrary.mapper.SpaceMapper;
import jnpf.doclibrary.service.DocLibraryService;
import jnpf.doclibrary.service.SpaceService;
import jnpf.entity.Information;
import jnpf.entity.InformationRubbish;
import jnpf.exception.HandleException;
import jnpf.file.FileUploadApi;
import jnpf.model.doclibrary.dto.*;
import jnpf.model.doclibrary.vo.*;
import jnpf.permission.UserApi;
import jnpf.permission.V2UserApi;
import jnpf.permission.vo.v2.user.UserBoundVO;
import jnpf.util.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 共享空间服务实现
 *
 * @author yanwenfu
 * @create 2023-07-20
 */
@Slf4j
@Service
public class SpaceServiceImpl implements SpaceService {

    @Resource
    private SpaceMapper spaceMapper;

    @Resource
    private InformationAuthorityMapper informationAuthorityMapper;

    @Resource
    private DocLibraryService docLibraryService;

    @Resource
    private UserProvider userProvider;

    @Autowired
    private UserApi userApi;
    @Autowired
    private V2UserApi v2UserApi;

    @Autowired
    private FileUploadApi fileUploadApi;

    @Override
    public List<MiniInformationVo> getMyResourceList(String pid) {

        List<String> ids = getIds(pid);
        // 根据ids查询资源信息
        if (ids.isEmpty()) {
            return new ArrayList<>();
        }
        List<MiniInformationVo> list = spaceMapper.getInformationList(new ArrayList<>(ids), "", "");
        if (!list.isEmpty()) {
            setCreateUserName(list);
            setInformationSize(list);
        }
        return list;
    }

    private List<String> getIds(String pid) {

        String userId = userProvider.get().getUserId();
//        Integer authorize = userApi.getUserModuleDataAuthorizesChem("resource", userId, "information_admin");
        List<String> ids;
        if (UserProvider.getUser().getIsAdministrator()) {
            // 超级管理员查看全部
            ids = spaceMapper.getAllByPid(pid);
        } else {
            ids = getMyResourceCommon(pid);
        }
        return ids;
    }

    private List<String> getMyResourceCommon(String pid) {

        // 1.本身拥有权限的空间/文件夹/文件，本身的权限优先级最高
        // 2.拥有权限的层级 向下覆盖 所有不是成员的文件/文件夹的权限
        // 3.拥有权限的层级 向上查看 查看完整路径有无自己有权限的，有则向下覆盖
        // 4.拥有权限的层级 向上查看 查看完整路径有无自己有权限的，无则只能查看

        String loginUserId = userProvider.get().getUserId();
        List<String> infoIds;
        if (pid.equals("0")) {
            infoIds = spaceMapper.getMyRootInfoIdByPath(loginUserId);
        } else {
            // 父级id
            String infoPath = spaceMapper.getInformationPath(pid);
            String[] infoIdArray = infoPath.split(",");
            // 子级id
            List<String> ids = spaceMapper.getChildrenInfoList(pid);
            ids.addAll(Arrays.asList(infoIdArray));
            // 查询存在pid的所有path中我拥有权限的informationId
            infoIds = spaceMapper.getMyInfoIdByPath(loginUserId, ids);
        }
        if (infoIds.isEmpty()) {
            return new ArrayList<>();
        }
        // 查出完整路径中包含infoIds的并且我拥有权限的文件/文件夹/空间
        List<String> pathList = spaceMapper.getMyResourcePath(infoIds);
        // 根据查出来的路径, 找到路径中pid的下一级
        Set<String> ids = new HashSet<>();
        pathList.forEach(path -> {
            String[] split = path.split(",");
            List<String> strList = new ArrayList<>(Arrays.asList(split));
            int index = strList.indexOf(pid);
            if (index != strList.size() - 1) {
                ids.add(strList.get(index + 1));
            }
        });
        return new ArrayList<>(ids);
    }

    @Override
    public PageInfo<MiniInformationVo> getMyResourcePage(String pid, InformationQueryDto queryDto) {

        List<String> ids = getIds(pid);
        // 根据ids查询资源信息
        if (ids.isEmpty()) {
            return new PageInfo<>();
        }
        PageHelper.startPage(queryDto.getCurrentPage(), queryDto.getPageSize());
        PageInfo<MiniInformationVo> page = new PageInfo<>(spaceMapper.getInformationList(new ArrayList<>(ids), queryDto.getQueryCondition(), queryDto.getQueryType()));
        if (page.getTotal() > 0) {
            // 查询用户信息
            setCreateUserName(page.getList());
            setInformationSize(page.getList());
        }
        return page;
    }

    private void setInformationSize(List<MiniInformationVo> list) {

        list.forEach(v -> {
            if (v.getClassification().equals(ConstantUtil.FILE_SPACE) || v.getClassification().equals(ConstantUtil.FILE_FOLDER)) {
                // 查询路径中被删除的部分
                List<String> delIds = spaceMapper.getDeletedFileIds(v.getId());
                // 查询空间/文件夹/文件占用空间
                Double usedSpaceSize = spaceMapper.getUsedSpaceSize(v.getId(), delIds);
                v.setFileSize(usedSpaceSize);
            }
        });
    }

    private void setCreateUserName(List<MiniInformationVo> list) {

        List<String> userIds = list.stream().map(MiniInformationVo::getCreatorUserId).distinct().collect(Collectors.toList());
//        List<PartUserInfoVo> userList = userApi.getInfoByIds(userIds);
        ActionResult<List<UserBoundVO>> userListResult = v2UserApi.getUserPrimaryBoundBatch(userIds, UserProvider.getUser().getTenantId());
        List<UserBoundVO> userList = userListResult.getData();
        Map<String, UserBoundVO> map = userList.stream().collect(Collectors.toMap(UserBoundVO::getId, Function.identity()));
        list.forEach(v -> {
            UserBoundVO user = map.get(v.getCreatorUserId());
            if (null != user) {
                v.setCreatorUserName(user.getUserName());
            }
        });
    }

    @Override
    public SpaceVo getInformationSpace(String id) {

        // 查询企业空间总容量
        String jsonStr = spaceMapper.getCommonConfigByKey(ConstantUtil.CONFIG_SPACE);
        SpaceVo space = new SpaceVo();
        space.setTotalSize(StringUtils.isEmpty(jsonStr) ? 0 : Integer.parseInt(jsonStr));
        // 查询路径中被删除的部分
        List<String> delIds = spaceMapper.getDeletedFileIds(id);
        // 查询空间/文件夹/文件占用空间
        Double usedSpaceSize = spaceMapper.getUsedSpaceSize(id, delIds);
        space.setUsedSpaceSize(usedSpaceSize);
        return space;
    }

    @Override
    public List<UserInfoVo> getInformationMemberList(String id) {

        // 查询关联的成员
        List<UserInfoVo> infoList = spaceMapper.getInformationMemberList(id);
        if (infoList.isEmpty()) {
            return new ArrayList<>();
        }
        List<String> userIds = infoList.stream().map(UserInfoVo::getUserId).collect(Collectors.toList());
        // 查询成员信息
//        List<PartUserInfoVo> list = userApi.getInfoByIds(userIds);
        ActionResult<List<UserBoundVO>> userListResult = v2UserApi.getUserPrimaryBoundBatch(userIds, UserProvider.getUser().getTenantId());
        List<UserBoundVO> list = userListResult.getData();
        Map<String, UserBoundVO> map = list.stream().collect(Collectors.toMap(UserBoundVO::getId, Function.identity()));
        infoList.forEach(v -> {
            UserBoundVO user = map.get(v.getUserId());
            if (null != user) {
                BeanUtils.copyProperties(user, v);
                v.setHeadIcon(UploaderUtil.uploaderImg(v.getHeadIcon()));
            }
        });
        return infoList;
    }

    @Override
    public InformationDetailVo getInformation(String id) throws Exception {

        Set<String> userIds = new HashSet<>();
        InformationDetailVo detail = spaceMapper.getInformation(id);
        if (null == detail) {
            throw new Exception("未找到记录");
        }
        userIds.add(detail.getOwner());
        userIds.add(detail.getCreatorUserId());
        if (null != detail.getLastModifyUserId()) {
            userIds.add(detail.getLastModifyUserId());
        }
        // 查看占用空间
        SpaceVo space = getInformationSpace(id);
        detail.setFileSize(space.getUsedSpaceSize());
        // 查询最近查看记录
        RecentlyViewedVo viewedVo = spaceMapper.getRecentlyViewInfo(id);
        if (null != viewedVo) {
            userIds.add(viewedVo.getUserId());
            detail.setLastViewUserId(viewedVo.getUserId());
            detail.setLastViewTime(viewedVo.getLastModifyTime());
        }
//        List<PartUserInfoVo> userList = userApi.getInfoByIds(new ArrayList<>(userIds));
        ActionResult<List<UserBoundVO>> userListResult = v2UserApi.getUserPrimaryBoundBatch(new ArrayList<>(userIds), UserProvider.getUser().getTenantId());
        List<UserBoundVO> userList = userListResult.getData();
        Map<String, UserBoundVO> map = userList.stream().collect(Collectors.toMap(UserBoundVO::getId, Function.identity()));
        UserBoundVO user = map.get(detail.getCreatorUserId());
        if (null != user) {
            detail.setCreatorUserName(user.getUserName());
        }
        UserBoundVO owner = map.get(detail.getOwner());
        if (null != owner) {
            detail.setOwnerName(owner.getUserName());
        }
        UserBoundVO updateUser = map.get(detail.getLastModifyUserId());
        if (null != detail.getLastModifyUserId() && null != updateUser) {
            detail.setLastModifyUserName(updateUser.getUserName());
        }
        if (null != viewedVo) {
            UserBoundVO viewUser = map.get(viewedVo.getUserId());
            if (null != viewUser) {
                detail.setLastViewUserName(viewUser.getUserName());
            }
        }
        return detail;
    }

    @Override
    public void addViewRecord(ViewDto viewDto) {

        UserInfo userInfo = userProvider.get();
        // 查看浏览记录是否存在
        RecentlyViewedVo viewedVo = spaceMapper.getRecentlyViewByUser(userInfo.getUserId(), viewDto.getInformationId());
        if (null != viewedVo) {
            // 存在 -> 更新
            spaceMapper.updateRecentlyViewInfo(viewedVo.getId());
        } else {
            // 不存在 -> 新增
            spaceMapper.addRecentlyViewRecord(FtbUtil.getId(), viewDto.getInformationId(), userInfo.getUserId());
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public List<RubbishInfoVo> getRubbishList(Integer queryType, String queryCondition) {

        String userId = getUserId();
        // 删除过期的回收站数据
        deleteOverdueRubbish(userId);
        List<RubbishInfoVo> list = spaceMapper.getRubbishList(queryType, queryCondition, userId);
        if (list.isEmpty()) {
            return new ArrayList<>();
        }
        setDaysRemaining(list);
        setSpaceName(list);
        return list;
    }

    private String getUserId() {
        UserInfo userInfo = userProvider.get();
//        Integer authorize = userApi.getUserModuleDataAuthorizesChem("resource", userInfo.getUserId(), "information_admin");
//        return authorize > 0 ? null : userInfo.getUserId();
        return userInfo.getIsAdministrator() ? null : userInfo.getUserId();
    }

    private void setSpaceName(List<RubbishInfoVo> list) {

        Set<String> set = new HashSet<>();
        // 所有的空间id
        list.forEach(v -> {
            String spaceId = v.getFilePath().split(",")[1];
            v.setSpaceId(spaceId);
            set.add(spaceId);
        });
        // 查询空间名称
        List<SpaceInfoVo> spaceList = spaceMapper.getSpaceNameList(new ArrayList<>(set));
        Map<String, SpaceInfoVo> map = spaceList.stream().collect(Collectors.toMap(SpaceInfoVo::getId, Function.identity()));
        list.forEach(v -> {
            SpaceInfoVo info = map.get(v.getSpaceId());
            if (null != info) {
                v.setSpaceName(info.getSpaceName());
            }
        });
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public PageInfo<RubbishInfoVo> getRubbishPage(RubbishQueryDto queryDto) {

        String userId = getUserId();
        // 删除过期的回收站数据
        deleteOverdueRubbish(userId);
        PageHelper.startPage(queryDto.getCurrentPage(), queryDto.getPageSize());
        PageInfo<RubbishInfoVo> page = new PageInfo<>(spaceMapper.getRubbishList(queryDto.getQueryType(), queryDto.getQueryCondition(), userId));
        if (page.getList().isEmpty()) {
            return page;
        }
        setDaysRemaining(page.getList());
        setSpaceName(page.getList());
        return page;
    }

    private void setDaysRemaining(List<RubbishInfoVo> list) {

        // 计算在回收站中的过期时间
        String json = spaceMapper.getCommonConfigByKey(ConstantUtil.CONFIG_RUBBISH_EXPIRE);
        if (StringUtils.isNotEmpty(json)) {
            int expireDay = Integer.parseInt(json);
            Date today = new Date();
            list.forEach(v -> {
                int diff = FtbUtil.dateDiff(v.getCreatorTime(), today);
                v.setDaysRemaining(expireDay - diff);
            });
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteRubbish(String rubbishId) {

        RubbishInfoVo rubbish = spaceMapper.getRubbishById(rubbishId);
        // 根据path查询所有要删除的项
        List<String> infoIds = spaceMapper.getInformationByPath(rubbish.getInformationId());
        // 删除ftb_information_rubbish记录
        spaceMapper.deleteRubbishByInfoIds(infoIds);
        // 删除ftb_information_recently_viewed
        spaceMapper.deleteViewByInfoIds(infoIds);
        // 删除ftb_information_authority
        spaceMapper.deleteAuthorityByInfoIds(infoIds);
        // 删除ftb_information记录
        spaceMapper.deleteInformationByInfoIds(infoIds);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateToUndelete(UndeleteDto undeleteDto) throws HandleException {

        // 查询回收站记录
        RubbishInfoVo rubbish = spaceMapper.getRubbishById(undeleteDto.getRubbishId());
        String userId = userProvider.get().getUserId();
        // 判断是否可以直接恢复, 不可以直接恢复, 恢复到空间下, 空间被删除, 无法恢复
        CheckRubbishVo vo = checkUndelete(rubbish.getRubbishId());
        if (vo.isResult() && StringUtils.isEmpty(vo.getMessage())) {
            // 直接恢复
            spaceMapper.updateToUndeleteById(rubbish.getInformationId(), userId);
        } else if (vo.isResult() && StringUtils.isNotEmpty(vo.getMessage())) {
            // 查询空间id
            InformationDetailVo information = spaceMapper.getInformation(rubbish.getInformationId());
            String spaceId = information.getFilePath().split(",")[1];
            // 生成新的path
            InformationDetailVo spaceInfo = spaceMapper.getInformation(spaceId);
            String newPath = spaceInfo.getFilePath() + information.getId() + ",";
            // 恢复到空间下
            spaceMapper.updateUndeleteToSpace(information.getId(), spaceId, newPath, userId);
        } else {
            // 无法恢复
            throw new HandleException(vo.getMessage());
        }
        // 删除回收站记录
        spaceMapper.deleteRubbishRecord(Stream.of(undeleteDto.getRubbishId()).collect(Collectors.toList()));
    }

    @Override
    public CheckRubbishVo checkUndelete(String rubbishId) {

        // 查询回收站信息
        RubbishInfoVo rubbish = spaceMapper.getRubbishById(rubbishId);
        //  查询空间已用大小
        SpaceVo spaceUse = getInformationSpace("0");
        // 查询回收站资源已用大小
        Double rubbishUse = spaceMapper.getRubbishUsedSpace(rubbish.getInformationId());
        if (FtbUtil.checkFileSize(rubbishUse + spaceUse.getUsedSpaceSize(), spaceUse.getTotalSize(), ConstantUtil.UNIT_G)) {
            return new CheckRubbishVo(false, "空间已满，无法恢复。如需要恢复，请删除部分文档/文件");
        }
        // 查询资源信息
        InformationDetailVo information = spaceMapper.getInformation(rubbish.getInformationId());
        if (information.getClassification().equals(ConstantUtil.FILE_SPACE)) {
            return new CheckRubbishVo(true, "");
        }
        // 查看资源path删除情况
        List<DeleteInfoVo> list = spaceMapper.getDeleteInfoByPath(information.getFilePath());
        DeleteInfoVo info = list.stream()
                .filter(v -> v.getEnabledMark().equals(ConstantUtil.NUM_TRUE) && !v.getInformationId().equals(rubbish.getInformationId()))
                .findFirst().orElse(null);
        if (null == info) {
            // 路径上没有其他节点被删除, 直接恢复
            return new CheckRubbishVo(true, "");
        } else {
            if (list.get(0).getEnabledMark().equals(ConstantUtil.NUM_TRUE)) {
                // 路径上有被删除的, 且空间被删除, 无法恢复
                return new CheckRubbishVo(false, "原所在空间已被删除，无法恢复");
            } else {
                // 路径上有被删除的, 空间没被删除, 恢复到空间下
                return new CheckRubbishVo(true, "原所在文件夹已被删除，将恢复至 所在共享空间 的根目录");
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Information addInformationFile(UploadDto uploadDto) throws Exception {

        String filePath;
        switch (uploadDto.getFileType()) {
            case ConstantUtil.FILE_TYPE_DOC:
                filePath = "/jnpf/doclibrary/document/空白文档.docx";
                break;
            case ConstantUtil.FILE_TYPE_XLS:
                filePath = "/jnpf/doclibrary/document/空白表格.xlsx";
                break;
            case ConstantUtil.FILE_TYPE_PPT:
                filePath = "/jnpf/doclibrary/document/空白PPT.pptx";
                break;
            default:
                throw new HandleException("文件类型错误");
        }
        String tmpName = filePath.substring(filePath.lastIndexOf("/") + 1, filePath.lastIndexOf("."));
        String tmpPath = System.getProperty("java.io.tmpdir") + filePath.substring(1);
        String uuid = RandomUtil.uuId();
        String suffix = filePath.substring(filePath.lastIndexOf(".") + 1);
        String fileName = uuid + "." + suffix;
        tmpPath = tmpPath.replace(tmpName, uuid);
        File file = new File(tmpPath);
        InputStream inputStream = this.getClass().getResourceAsStream(filePath);
        if (null == inputStream) {
            throw new HandleException("文件读取失败");
        }
        FileUtils.copyInputStreamToFile(inputStream, file);
        inputStream.close();
        MultipartFile multiFile;
        try {
            multiFile = new MockMultipartFile(uuid, file.getName(), MediaType.MULTIPART_FORM_DATA_VALUE, new FileInputStream(file));
        } catch (FileNotFoundException e) {
            throw new HandleException("文件未找到");
        }
        String userId = userProvider.get().getUserId();
        String uploadPath = String.format(ConstantUtil.UPLOAD_FOLDER, userId);
        FileInfo fileInfo = fileUploadApi.uploadFile(multiFile, uploadPath, fileName);
        fileInfo.setUrl(fileInfo.getUrl().replace("/jnpf-resource-1304460613/", ""));
        FileUtil.deleteFile(tmpPath);
        // 生成ftb_information数据
        Information information = getInformationData(fileInfo, userId, suffix, tmpName, uploadDto);
        executeSql(information, userId);
        return information;
    }

    private void executeSql(Information information, String userId) {

        // 新增资料库记录
        spaceMapper.addInformation(information);
        // 新增权限记录
        informationAuthorityMapper.addUserAuthority(FtbUtil.getId(), userId, information.getId(), 0, userId);
        // 新增日志
        docLibraryService.addInformationLog(information.getId(), information.getClassification(), userId, userProvider.get().getUserName(), "上传", null);
    }

    @Override
    public void singleFileUploads(HttpServletRequest request, HttpServletResponse response) throws Exception {

        log.info("进入回调...");
        PrintWriter writer = response.getWriter();

        Scanner scanner = new Scanner(request.getInputStream(), "GBK").useDelimiter("\\A");
        String body = scanner.hasNext() ? scanner.next() : "";
        JSONObject jsonObj = new JSONObject(body);
        log.error("body：{}", jsonObj);
        if (Integer.parseInt(jsonObj.get("status").toString()) == 2 || Integer.parseInt(jsonObj.get("status").toString()) == 6) {

            String downloadUri = (String) jsonObj.get("url");
            URL url = new URL(downloadUri);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            InputStream inputStream = connection.getInputStream();
            // 前端加了"_"以获取最新数据
            String id = request.getParameter("id");
            if (StringUtil.isEmpty(id)) {
                try {
                    String key = jsonObj.get("key").toString();
                    id = key.split("_")[0];
                } catch (Exception e) {
                    throw new HandleException("获取资料库id失败...");
                }
            }
            if (StringUtil.isEmpty(id)) {
                throw new HandleException("获取资料库id失败...");
            }
            InformationDetailVo information = spaceMapper.getInformation(id);
            if (null == information) {
                throw new HandleException("查询资料库数据失败...");
            }
            String dbUrl = information.getFileUrl();
            log.info("数据库：{}", dbUrl);
            // 上传到腾讯云 路径覆盖
            String fileName = dbUrl.substring(dbUrl.lastIndexOf("/") + 1);
            MultipartFile multiFile = new MockMultipartFile(fileName.substring(0, fileName.lastIndexOf(".")), fileName, MediaType.MULTIPART_FORM_DATA_VALUE, inputStream);
            inputStream.close();
            connection.disconnect();
            log.info("multiFile: {}, fileName: {}", multiFile.getName(), fileName);
            // 判断文件大小
            SpaceVo space = getInformationSpace("0");
            if (FtbUtil.checkFileSize((double) multiFile.getSize() + space.getUsedSpaceSize(), space.getTotalSize(), ConstantUtil.UNIT_G)) {
                log.error("空间已满，编辑失败。如需要编辑，请删除部分文档/文件");
                writer.write("{\"error\":-1, \"message\":\"空间已满，编辑失败。如需要编辑，请删除部分文档/文件\"}");
                return;
            }
            String[] split = dbUrl.split("/");
            StringBuilder sb = new StringBuilder();
            for (int i = split.length - 1; i > 0; i--) {
                if (!split[i].equals("jnpf-resources")) {
                    sb.insert(0, split[i]).insert(0, "/");
                } else {
                    sb.replace(0, 1, "");
                    break;
                }
            }
            log.info(sb.toString());
            String uploadPath = sb.toString().replaceAll(fileName, "");
            FileInfo fileInfo = fileUploadApi.uploadFileCustomName(multiFile, uploadPath, fileName);
            if (null == fileInfo) {
                log.info("上传文件失败...");
                writer.write("{\"error\":-1}");
                return;
            }
            log.info("返回路径: {}", fileInfo.getUrl());
            // 生成修改日志
            Object users = jsonObj.get("users");
            JSONArray array = new JSONArray(users);
            List<String> userIds = array.toList(String.class);
            // 修改文件大小
            spaceMapper.updateFileSize(information.getId(), fileInfo.getSize(), userIds.get(0));
            String tenantId = request.getParameter("tenantId");
            log.error(tenantId);
            ActionResult<List<UserBoundVO>> userResult = v2UserApi.getUserPrimaryBoundBatch(userIds, tenantId);
            List<UserBoundVO> userList = userResult.getData();
            if (null != userList && !userList.isEmpty()) {
                for (UserBoundVO user : userList) {
                    docLibraryService.addInformationLog(information.getId(), information.getClassification(), user.getId(), user.getUserName(), "编辑", null);
                }
            }
            jsonObj.clear();
            writer.write("{\"error\":0}");
        } else if (Integer.parseInt(jsonObj.get("status").toString()) == 3 || Integer.parseInt(jsonObj.get("status").toString()) == 7) {
            jsonObj.clear();
            writer.write("{\"error\":-1}");
        } else {
            writer.write("{\"error\":0}");
        }
    }

    @Override
    public FileInfo uploadFile(MultipartFile multipartFile, String fileName) {

        String userId = userProvider.get().getUserId();
        String uploadPath = String.format(ConstantUtil.UPLOAD_FOLDER, userId);
        FileInfo fileInfo = fileUploadApi.uploadFileCustomName(multipartFile, uploadPath, StringUtils.isEmpty(fileName) ? multipartFile.getName() : fileName);
        fileInfo.setUrl(fileInfo.getUrl().replace("/jnpf-resource-1304460613/", ""));
        fileInfo.setFilename(fileInfo.getFilename().substring(0, fileInfo.getFilename().lastIndexOf(".")));
        return fileInfo;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addInformationDetails(List<InfoDetailDto> list) {

        UserInfo userInfo = userProvider.get();
        list.forEach(info -> {
            Information information = getInfoByDetailDto(info, userInfo);
            executeSql(information, userInfo.getUserId());
        });
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteOverdueRubbish(String userId) {

        // 查询配置的有效天数
        String keepDay = spaceMapper.getCommonConfigByKey(ConstantUtil.CONFIG_RUBBISH_EXPIRE);
        // 查询过期的垃圾文件
        List<InformationRubbish> list = spaceMapper.getExpireRubbish(keepDay, userId);
        if (list.isEmpty()) {
            return;
        }
        List<String> collect = list.stream().map(InformationRubbish::getInformationId).collect(Collectors.toList());
        // 根据path查询所有要删除的项
        List<String> infoIds = spaceMapper.getInformationByIdsPath(collect);
        // 删除ftb_information_rubbish记录
        spaceMapper.deleteRubbishByInfoIds(infoIds);
        // 删除ftb_information_recently_viewed
        spaceMapper.deleteViewByInfoIds(infoIds);
        // 删除ftb_information_authority
        spaceMapper.deleteAuthorityByInfoIds(infoIds);
        // 删除ftb_information记录
        spaceMapper.deleteInformationByInfoIds(infoIds);
    }

    @Override
    public void deleteOverdueViewRecord() {

        int i = spaceMapper.deleteOverdueViewRecord();
        log.info("删除了{}条记录", i);
    }

    private Information getInfoByDetailDto(InfoDetailDto info, UserInfo userInfo) {

        Information information = new Information();
        information.setId(FtbUtil.getId());
        information.setFileName(info.getFileName());
        information.setFilesize(Double.longBitsToDouble(Double.doubleToLongBits(info.getFileSize())));
        information.setFileUrl(info.getFileUrl());
        information.setOwner(userInfo.getUserId());
        information.setFileSuffix(info.getFileSuffix());
        information.setClassification(info.getClassification());
        information.setFileType(info.getFileType());
        String path = getFIlePath(info.getFilePid(), information.getId());
        information.setFilePath(path);
        information.setFilePid(info.getFilePid());
        information.setCreatorUserId(userInfo.getUserId());
        information.setLastModifyUserId(userInfo.getUserId());
        return information;
    }

    private Information getInformationData(FileInfo fileInfo, String userId, String suffix, String fName, UploadDto uploadDto) {

        Information info = new Information();
        info.setId(FtbUtil.getId());
        info.setFileName(fName);
        info.setFilesize(FtbUtil.getFileSize(fileInfo.getSize()));
        info.setFileUrl(fileInfo.getUrl());
        info.setOwner(userId);
        info.setFileSuffix(suffix);
        info.setClassification(3);
        info.setFileType(uploadDto.getFileType());
        String pid = uploadDto.getPid();
        String path = getFIlePath(pid, info.getId());
        info.setFilePath(path);
        info.setFilePid(pid);
        info.setCreatorUserId(userId);
        info.setLastModifyUserId(userId);
        return info;
    }

    private String getFIlePath(String pid, String id) {

        String path;
        if (pid.equals("0")) {
            path = "0," + id + ",";
        } else {
            InformationDetailVo information = spaceMapper.getInformation(pid);
            path = information.getFilePath() + id + ",";
        }
        return path;
    }


    /**
     * 查询我的资源文件夹
     *
     * @param folderName 文件夹名称
     * @return 文件夹列表
     */
    @Override
    public List<MiniInformationTreeVo> queryMyResourceFolder(String folderName) {
        List<String> powerInfoIds = new ArrayList<>();
        UserInfo user = UserProvider.getUser();
        if (!user.getIsAdministrator()) {
            powerInfoIds = spaceMapper.queryAllPowerInfoIds(user.getUserId());
            if (powerInfoIds.isEmpty()) {
                return new ArrayList<>();
            }
        }
        List<MiniInformationTreeVo> list = spaceMapper.queryMyResourceFolder(folderName, powerInfoIds);
        if (CollectionUtil.isNotEmpty(list)) {
            return buildTree(list);
        }
        return list;
    }

    /**
     * 查询我的文件
     *
     * @param req 参数
     * @return 分页返回文件列表
     */
    @Override
    public PageInfo<MiniInformationVo> queryMyFilesForFolderId(QueryMyFilesReq req) {

        PageHelper.startPage(req.getCurrentPage(), req.getPageSize());
        return new PageInfo<>(spaceMapper.queryMyFilesForFolderId(req));

    }

    public static List<MiniInformationTreeVo> buildTree(List<MiniInformationTreeVo> list) {
        if (list == null || list.isEmpty()) {
            return new ArrayList<>();
        }

        // 1. 创建 Map 用于快速查找节点
        Map<String, MiniInformationTreeVo> nodeMap = new HashMap<>();
        for (MiniInformationTreeVo node : list) {
            nodeMap.put(node.getId(), node);
        }

        // 2. 构建树结构
        List<MiniInformationTreeVo> rootNodes = new ArrayList<>();
        for (MiniInformationTreeVo node : list) {
            String parentId = node.getFilePid();
            if ("0".equals(parentId) || parentId == null) {
                // 根节点直接加入结果集
                rootNodes.add(node);
            } else {
                // 查找父节点并添加当前节点为其子节点
                MiniInformationTreeVo parent = nodeMap.get(parentId);
                if (parent != null) {
                    if (parent.getChildren() == null) {
                        parent.setChildren(new ArrayList<>());
                    }
                    parent.getChildren().add(node);
                }
            }
        }

        return rootNodes;
    }

}
