package com.vctgo.file.service.impl;

import java.util.*;
import java.util.stream.Collectors;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.nacos.shaded.com.google.common.base.Splitter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.vctgo.common.core.constant.HttpStatus;
import com.vctgo.common.core.constant.RoleConstants;
import com.vctgo.common.core.constant.SecurityConstants;
import com.vctgo.common.core.domain.R;
import com.vctgo.common.core.exception.ServiceException;
import com.vctgo.common.core.utils.StrUtils;
import com.vctgo.common.mybatisplus.query.QueryWrapperX;
import com.vctgo.common.redis.service.RedisService;
import com.vctgo.common.security.utils.SecurityUtils;
import com.vctgo.file.domain.FileAuthGroup;
import com.vctgo.file.mapper.FileAuthGroupMapper;
import com.vctgo.file.mapper.FileInfoMapper;
import com.vctgo.file.service.IFileCommonService;
import com.vctgo.file.utils.ConstantUtils;
import com.vctgo.system.api.RemoteUserService;
import com.vctgo.system.api.domain.FileInfo;
import com.vctgo.system.api.domain.SysUserTempalte;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.vctgo.file.mapper.FileReUserOperateMapper;
import com.vctgo.file.domain.FileReUserOperate;
import com.vctgo.file.service.IFileReUserOperateService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.vctgo.common.core.text.Convert;
import com.vctgo.common.core.utils.ServletUtils;
import com.vctgo.common.mybatisplus.constant.MybatisPageConstants;

import static com.vctgo.common.core.domain.R.SUCCESS;

/**
 * 文件与用户的操作关系Service业务层处理
 *
 * @author caesar
 * @date 2024-01-31
 */
@Slf4j
@Service
public class FileReUserOperateServiceImpl implements IFileReUserOperateService {

    @Autowired
    private FileReUserOperateMapper fileReUserOperateMapper;

    @Autowired
    private FileInfoMapper fileInfoMapper;

    @Autowired
    private FileAuthGroupMapper fileAuthGroupMapper;

    @Autowired
    private IFileCommonService fileCommonService;

    @Autowired
    private RemoteUserService remoteUserService;

    /**
     * 查询文件与用户的操作关系
     *
     * @param id 文件与用户的操作关系主键
     * @return 文件与用户的操作关系
     */
    @Override
    public FileReUserOperate selectFileReUserOperateById(Long id) {
        return fileReUserOperateMapper.selectById(id);
    }

    /**
     * 查询文件与用户的操作关系列表-分页
     *
     * @param fileReUserOperate 文件与用户的操作关系
     * @return 文件与用户的操作关系
     */
    @Override
    public IPage<FileReUserOperate> selectFileReUserOperatePage(FileReUserOperate fileReUserOperate) {
        Page mpPage = new Page(Convert.toLong(ServletUtils.getParameterToInt(MybatisPageConstants.PAGE_NUM), 1L)
                , Convert.toLong(ServletUtils.getParameterToInt(MybatisPageConstants.PAGE_SIZE), 10L));
        return fileReUserOperateMapper.selectFileReUserOperateList(mpPage, fileReUserOperate);
    }

    /**
     * 查询文件与用户的操作关系列表
     *
     * @param fileReUserOperate 文件与用户的操作关系
     * @return 文件与用户的操作关系
     */
    @Override
    public List<FileReUserOperate> selectFileReUserOperateList(FileReUserOperate fileReUserOperate) {
        return fileReUserOperateMapper.selectFileReUserOperateList(fileReUserOperate);
    }

    /**
     * 新增文件与用户的操作关系
     *
     * @param fileReUserOperate 文件与用户的操作关系
     * @return 结果
     */

    @Override
    public int insertFileReUserOperate(FileReUserOperate fileReUserOperate) {
        return fileReUserOperateMapper.insert(fileReUserOperate);
    }

    /**
     * 修改文件与用户的操作关系
     *
     * @param fileReUserOperate 文件与用户的操作关系
     * @return 结果
     */
    @Override
    public int updateFileReUserOperate(FileReUserOperate fileReUserOperate) {
        return fileReUserOperateMapper.updateById(fileReUserOperate);
    }

    /**
     * 逻辑删除文件与用户的操作关系
     *
     * @param ids 需要删除的文件与用户的操作关系主键
     * @return 结果
     */
    @Override
    public int logicalDeleteFileReUserOperateByIds(Long[] ids) {
        FileReUserOperate fileReUserOperate = new FileReUserOperate();
        fileReUserOperate.setUpdateById(SecurityUtils.getUserId());
        fileReUserOperate.setUpdateTime(new Date());
        fileReUserOperate.setIsDeleted(ConstantUtils.IS_DELETED_1);
        return fileReUserOperateMapper.logicalDeleteFileReUserOperateByIds(ids, fileReUserOperate);
    }

    /**
     * 批量删除文件与用户的操作关系
     *
     * @param ids 需要删除的文件与用户的操作关系主键
     * @return 结果
     */
    @Override
    public int deleteFileReUserOperateByIds(Long[] ids) {
        return fileReUserOperateMapper.deleteFileReUserOperateByIds(ids);
    }

    /**
     * 删除文件与用户的操作关系信息
     *
     * @param id 文件与用户的操作关系主键
     * @return 结果
     */
    @Override
    public int deleteFileReUserOperateById(Long id) {
        return fileReUserOperateMapper.deleteById(id);
    }

    @Override
    public List<FileReUserOperate> getFileReUserOperateList(String fileId) {
        List<FileReUserOperate> fileReUserOperateList = fileReUserOperateMapper.selectList(new QueryWrapperX<FileReUserOperate>().lambda()
                .eq(FileReUserOperate::getFileId, fileId)
                .eq(FileReUserOperate::getTenantId, SecurityUtils.getTenantId())
                .eq(FileReUserOperate::getIsDeleted, ConstantUtils.IS_DELETED_0));
        Set<String> userIdSet = fileReUserOperateList.stream().map(FileReUserOperate::getUserId).map(String::valueOf).collect(Collectors.toSet());

        // 设置继承
        LambdaQueryWrapper<FileInfo> fileInfoWrapper = Wrappers.lambdaQuery(FileInfo.class)
                .eq(FileInfo::getIsDeleted, ConstantUtils.IS_DELETED_0)
                .eq(FileInfo::getFileIsHide, ConstantUtils.IS_DELETED_0)
                .eq(FileInfo::getTenantId, SecurityUtils.getTenantId())
                .eq(FileInfo::getId, fileId);
        FileInfo fileInfo = fileInfoMapper.selectOne(fileInfoWrapper);
        if (Objects.nonNull(fileInfo)) {
            List<FileReUserOperate> fileReUserOperateExtendPermisson = fileReUserOperateMapper.selectFileByTenantIdAndFileId(SecurityUtils.getTenantId().toString(), fileInfo.getAncestors());
            fileReUserOperateExtendPermisson = fileReUserOperateExtendPermisson.stream().filter(fileReUserOperate -> !userIdSet.contains(fileReUserOperate.getUserId().toString())).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(fileReUserOperateExtendPermisson)) {
                List<FileReUserOperate> fileReUserOperates = new ArrayList<>();
                List<String> ancetorsStringList = Lists.newArrayList(Splitter.on(",").splitToList(fileInfo.getAncestors()).iterator());
                Collections.reverse(ancetorsStringList);
                Map<Long, List<FileReUserOperate>> userIdMap = fileReUserOperateExtendPermisson.stream().collect(Collectors.groupingBy(FileReUserOperate::getUserId));
                userIdMap.forEach((userId, userOperateList) -> {
                    for (String ancetorsString : ancetorsStringList) {
                        Optional<FileReUserOperate> userOperateOptional = userOperateList.stream().filter(fileReUserOperate -> fileReUserOperate.getFileId().toString().equals(ancetorsString)).findFirst();
                        if (userOperateOptional.isPresent()) {
                            FileReUserOperate fileReUserOperate = userOperateOptional.get();
                            fileReUserOperate.setId(null);
                            fileReUserOperate.setFileId(Long.valueOf(fileId));
                            fileReUserOperate.setUserId(userId);
                            if ("0".equals(fileInfo.getFileIsDirectory())) {
                                List<FileAuthGroup> fileAuthGroups = fileAuthGroupMapper.selectList();
                                Optional<FileAuthGroup> fileAuthGroupOptional = null;
                                switch (fileReUserOperate.getFileUserAuthCode()) {
                                    case ConstantUtils.FILE_AUTH_GROUP_MANAGE:
                                        fileAuthGroupOptional = fileAuthGroups.stream().filter(fileAuthGroup -> fileAuthGroup.getGroupCode().equals(ConstantUtils.DOC_AUTH_GROUP_MANAGE)).findFirst();
                                        break;
                                    case ConstantUtils.FILE_AUTH_GROUP_AUTH_MANAGE:
                                        fileAuthGroupOptional = fileAuthGroups.stream().filter(fileAuthGroup -> fileAuthGroup.getGroupCode().equals(ConstantUtils.DOC_AUTH_GROUP_AUTH_MANAGE)).findFirst();
                                        break;
                                    case ConstantUtils.FILE_AUTH_GROUP_SHOW_DOWN:
                                        fileAuthGroupOptional = fileAuthGroups.stream().filter(fileAuthGroup -> fileAuthGroup.getGroupCode().equals(ConstantUtils.DOC_AUTH_GROUP_SHOW_DOWN)).findFirst();
                                        break;
                                    case ConstantUtils.FILE_AUTH_GROUP_UP_DOWN:
                                        fileAuthGroupOptional = fileAuthGroups.stream().filter(fileAuthGroup -> fileAuthGroup.getGroupCode().equals(ConstantUtils.DOC_AUTH_GROUP_UP_DOWN)).findFirst();
                                        break;
                                    case ConstantUtils.FILE_AUTH_GROUP_SHOW:
                                        fileAuthGroupOptional = fileAuthGroups.stream().filter(fileAuthGroup -> fileAuthGroup.getGroupCode().equals(ConstantUtils.DOC_AUTH_GROUP_SHOW)).findFirst();
                                        break;
                                }
                                if (Objects.nonNull(fileAuthGroupOptional) && fileAuthGroupOptional.isPresent()) {
                                    FileAuthGroup fileAuthGroup = fileAuthGroupOptional.get();
                                    fileReUserOperate.setFileUserAuthCode(fileAuthGroup.getGroupCode());
                                    fileReUserOperate.setFileUserAuthId(fileAuthGroup.getId());
                                    fileReUserOperate.setFileUserAuthDesc(fileAuthGroup.getGroupDesc());
                                }
                            }
                            fileReUserOperates.add(fileReUserOperate);
                            break;
                        }
                    }
                });
                fileReUserOperateList.addAll(fileReUserOperates);
            }
        }

        if (CollectionUtils.isNotEmpty(fileReUserOperateList)) {
            // TODO 用户为超级管理员和文件资源管理员不显示
            R<List<Long>> listR = remoteUserService.selectUserAndRoleList(RoleConstants.ROLE_KEY_FILE_RESOURCE_USER);
            if (listR.getCode() != HttpStatus.SUCCESS) {
                throw new ServiceException("获取当前文件与用户的操作关系失败");
            }
            List<Long> userIdList = listR.getData();
            fileReUserOperateList.removeIf(fileReUserOperate -> userIdList.contains(fileReUserOperate.getUserId()));

            if (CollectionUtils.isNotEmpty(fileReUserOperateList)) {
                //获取用户昵称和手机号
                List<SysUserTempalte> sysUserTempalteList = fileCommonService.selectSysUserTemplateListByTenantId(SecurityUtils.getTenantId());
                if (CollectionUtils.isNotEmpty(sysUserTempalteList)) {
                    fileReUserOperateList.forEach(fileReUserOperate -> {
                        Optional<SysUserTempalte> userTempalteOptional = sysUserTempalteList.stream()
                                .filter(sysUserTempalte -> sysUserTempalte.getUserId().toString()
                                        .equals(fileReUserOperate.getUserId().toString()))
                                .findAny();
                        if (userTempalteOptional.isPresent()) {
                            SysUserTempalte sysUserTempalte = userTempalteOptional.get();
                            fileReUserOperate.setUserName(sysUserTempalte.getNickName());
                            fileReUserOperate.setPhoneNumber(sysUserTempalte.getPhonenumber());
                        }
                    });
                }
            }
        }

        return fileReUserOperateList;
    }

    @Override
    public FileReUserOperate selectByIdAndAuthCode(String fileId, String userId, List<String> AuthCodes) {
        LambdaQueryWrapper<FileReUserOperate> lambdaQueryWrapper = new QueryWrapper<FileReUserOperate>().lambda();
        lambdaQueryWrapper.eq(FileReUserOperate::getFileId,fileId);
        lambdaQueryWrapper.eq(FileReUserOperate::getUserId,userId);
        lambdaQueryWrapper.in(FileReUserOperate::getFileUserAuthCode,AuthCodes);
        return fileReUserOperateMapper.selectOne(lambdaQueryWrapper);
    }

    @Override
    public long selectCountFileReUserOperate(LambdaQueryWrapper<FileReUserOperate> queryWrapper) {
        return fileReUserOperateMapper.selectCount(queryWrapper);
    }
}
