package com.vctgo.file.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.base.Splitter;
import com.vctgo.common.core.constant.RoleConstants;
import com.vctgo.common.core.web.controller.BaseController;
import com.vctgo.common.core.web.domain.AjaxResult;
import com.vctgo.common.security.annotation.Logical;
import com.vctgo.common.security.annotation.RequiresPermissions;
import com.vctgo.common.security.utils.SecurityUtils;
import com.vctgo.file.domain.FileReUserOperate;
import com.vctgo.file.domain.dto.FileInfoAuthDto;
import com.vctgo.file.mapper.FileReUserOperateMapper;
import com.vctgo.file.service.IFileInfoService;
import com.vctgo.file.service.IFileReUserOperateService;
import com.vctgo.file.utils.ConstantUtils;
import com.vctgo.system.api.domain.FileInfo;
import com.vctgo.system.api.domain.SysRole;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 文件服务
 *
 * @author vctgo
 */
@Api(tags = "文件服务基础业务")
@RestController
@RequestMapping("/atAll")
public class JnrzFileInfoController extends BaseController {
    private static final Logger log = LoggerFactory.getLogger(JnrzFileInfoController.class);
    @Autowired
    private FileReUserOperateMapper fileReUserOperateMapper;
    @Autowired
    private IFileInfoService fileInfoService;
    @Autowired
    private IFileReUserOperateService fileReUserOperateService;

    @ApiOperation(value = "通过租户Id和服务名创建默认文件夹")
    @Transactional
    @GetMapping("/inner/init")
    public AjaxResult initMkdirByTenantId(@RequestParam("tenantId") Long tenantId, @RequestParam("serviceName") String serviceName, @RequestParam("fileName") String fileName) {
        fileInfoService.initMkdirByTenantId(tenantId, serviceName, fileName);
        return AjaxResult.success();
    }

    @ApiOperation(value = "文件资源-分页")
    @Transactional
    @GetMapping("/page")
    @RequiresPermissions("file:manage:page")
    public AjaxResult getFileManagePage(FileInfo fileInfo) {
        FileInfoAuthDto fileManagePage = fileInfoService.findFileManagePage(fileInfo);
        return AjaxResult.success(fileManagePage);
    }

    @ApiOperation(value = "富力桃园定制化文件资源-分页")
    @Transactional
    @GetMapping("/v2/page")
    public AjaxResult getFileManagePageV2(FileInfo fileInfo) {
        FileInfoAuthDto fileManagePage = fileInfoService.findFileManagePageV2(fileInfo);
        return AjaxResult.success(fileManagePage);
    }

    @ApiOperation(value = "重命名")
    @Transactional
    @RequestMapping("/rename/{id}")
    @RequiresPermissions(value = {"file:manage:rename", "file:operate:auth"}, logical = Logical.OR)
    public AjaxResult doReFileName(@PathVariable Long id, @RequestParam("rename") String rename) {
        FileInfo fileInfo = fileInfoService.selectById(id);
        //文件夹
        if (ConstantUtils.IS_DIRECTORY_FILE_1.equals(fileInfo.getFileIsDirectory())) {
            //同目录下文件夹名称不可重复，如文件夹名称重复提示“文件夹名称重复，保存失败”。
            List<FileInfo> fileInfoList = fileInfoService.selectListByFileInfo(FileInfo.builder()
                    .tenantId(SecurityUtils.getTenantId())
                    .fileParentId(fileInfo.getFileParentId())
                    .fileName(rename)
                    .fileIsDirectory(ConstantUtils.IS_DIRECTORY_FILE_1)
                    .isDeleted(ConstantUtils.IS_DELETED_0)
                    .fileIsHide(ConstantUtils.IS_DELETED_0).build());
            if (CollectionUtils.isNotEmpty(fileInfoList)) {
                for (FileInfo info : fileInfoList) {
                    if (!(fileInfo.getId() + "").equals(info.getId() + "")) {
                        return AjaxResult.error("文件名称重复，保存失败");
                    }
                }
            }
        }
        //文件
        if (ConstantUtils.IS_DIRECTORY_FILE_0.equals(fileInfo.getFileIsDirectory())) {
            //同目录下、相同文件类型下、文件名称不可重复，如文件夹称重复提示“文件名称重复，保存失败”。
            List<FileInfo> fileInfoList = fileInfoService.selectListByFileInfo(FileInfo.builder()
                    .tenantId(SecurityUtils.getTenantId())
                    .fileParentId(fileInfo.getFileParentId())
                    .fileName(rename.replace("." + FilenameUtils.getExtension(rename), ""))
                    .fileExtension(FilenameUtils.getExtension(rename))
                    .fileIsDirectory(ConstantUtils.IS_DIRECTORY_FILE_0)
                    .isDeleted(ConstantUtils.IS_DELETED_0)
                    .fileIsHide(ConstantUtils.IS_DELETED_0).build());
            if (CollectionUtils.isNotEmpty(fileInfoList)) {
                for (FileInfo info : fileInfoList) {
                    if (!(fileInfo.getId() + "").equals(info.getId() + "")) {
                        return AjaxResult.error("文件名称重复，保存失败");
                    }
                }
            }
        }
        fileInfoService.doReFileName(id, rename);
        return AjaxResult.success();
    }

    @ApiOperation(value = "批量删除")
    @Transactional
    @RequestMapping("/hide/{ids}")
    @RequiresPermissions(value = {"file:manage:hide", "file:manage:batch:hide", "file:operate:auth"}, logical = Logical.OR)
    public AjaxResult doBatchHideFile(@PathVariable String ids) {
        fileInfoService.doBatchHideFile(ids);
        return AjaxResult.success();
    }

    @ApiOperation(value = "移动文件夹树")
    @Transactional
    @RequestMapping("/move/tree")
    public AjaxResult doMoveFileTree() {
        List<FileInfo> fileInfoList = fileInfoService.doMoveFileTree();
        return AjaxResult.success(fileInfoList);
    }

    @ApiOperation(value = "批量移动")
    @Transactional
    @RequestMapping("/move/{fileParentId}/{ids}")
    @RequiresPermissions(value = {"file:manage:move", "file:manage:batch:move", "file:operate:auth"}, logical = Logical.OR)
    public AjaxResult doBatchMoveFile(@PathVariable String fileParentId, @PathVariable String ids) {
        FileInfo parentFile = fileInfoService.selectById(Long.valueOf(fileParentId));
        List<FileInfo> fileInfoList = fileInfoService.selectByIds(ids);
        //验证移动位置是否正确
        for (FileInfo fileInfo : fileInfoList) {
            if (ConstantUtils.IS_DIRECTORY_FILE_1.equals(fileInfo.getFileIsDirectory())) {
                if (fileParentId.equals(fileInfo.getFileParentId().toString())) {
                    return AjaxResult.error("请勿将文件夹移动到自身或其子目录下");
                }
                if (fileParentId.equals(fileInfo.getId().toString())) {
                    return AjaxResult.error("请勿将文件夹移动到自身或其子目录下");
                }
                if (parentFile.getAncestors().contains(fileInfo.getId().toString())) {
                    return AjaxResult.error("请勿将文件夹移动到自身或其子目录下");
                }
            }
            if (ConstantUtils.IS_DIRECTORY_FILE_0.equals(fileInfo.getFileIsDirectory())) {
                if (fileParentId.equals(fileInfo.getFileParentId().toString())) {
                    return AjaxResult.error("请勿将文件移动到当前文件夹下");
                }
            }
        }
        //验权限
        for (FileInfo fileInfo : fileInfoList) {
            if (ConstantUtils.IS_DIRECTORY_FILE_1.equals(fileInfo.getFileIsDirectory())) {
                // 非超级管理员、文件资源管理员，移动文件需要校验权限
                List<String> roleKeyList = SecurityUtils.getLoginUser().getSysRolesList().stream().map(SysRole::getRoleKey).collect(Collectors.toList());
                if (!roleKeyList.contains(RoleConstants.ROLE_KEY_ADMIN) && !roleKeyList.contains(RoleConstants.ROLE_KEY_FILE_RESOURCE_USER)) {
                    long authCount1 = fileReUserOperateService.selectCountFileReUserOperate(new QueryWrapper<FileReUserOperate>().lambda()
                            .eq(FileReUserOperate::getTenantId, SecurityUtils.getTenantId())
                            .eq(FileReUserOperate::getFileId, parentFile.getId())
                            .eq(FileReUserOperate::getUserId, SecurityUtils.getUserId())
                            .eq(FileReUserOperate::getIsDeleted, ConstantUtils.IS_DELETED_0));
                    if (authCount1 == 0L) {
                        //继承权限验证
                        List<String> ancestorsFileIdList = Splitter.on(",").splitToStream(parentFile.getAncestors()).collect(Collectors.toList());
                        Collections.reverse(ancestorsFileIdList);
                        List<FileReUserOperate> fileReUserOperateRetainList = fileReUserOperateMapper.selectGroupPermissionListByUserIdAndFileId(ancestorsFileIdList, String.valueOf(SecurityUtils.getUserId()));
                        for (String fileId : ancestorsFileIdList) {
                            Optional<FileReUserOperate> fileReUserOperateOptional = fileReUserOperateRetainList.stream().filter(fileReUserOperate -> fileId.equals(fileReUserOperate.getFileId().toString())).findFirst();
                            if (fileReUserOperateOptional.isPresent()) {
                                FileReUserOperate fileReUserOperate = fileReUserOperateOptional.get();
                                if (fileReUserOperate.getFileUserAuthCode().equals(ConstantUtils.FILE_AUTH_GROUP_AUTH_MANAGE) || fileReUserOperate.getFileUserAuthCode().equals(ConstantUtils.FILE_AUTH_GROUP_MANAGE)) {

                                } else {
                                    return AjaxResult.error("请勿将文件夹移动到无管理权限的目录下，请联系管理员分配后再试");
                                }
                            }
                        }
                    } else {
                        List<String> fileUserAuthCodeList = new ArrayList<>();
                        fileUserAuthCodeList.add(ConstantUtils.FILE_AUTH_GROUP_MANAGE);
                        fileUserAuthCodeList.add(ConstantUtils.FILE_AUTH_GROUP_AUTH_MANAGE);
                        long authCount2 = fileReUserOperateService.selectCountFileReUserOperate(new QueryWrapper<FileReUserOperate>().lambda()
                                .eq(FileReUserOperate::getTenantId, SecurityUtils.getTenantId())
                                .eq(FileReUserOperate::getFileId, parentFile.getId())
                                .eq(FileReUserOperate::getUserId, SecurityUtils.getUserId())
                                .in(FileReUserOperate::getFileUserAuthCode, fileUserAuthCodeList)
                                .eq(FileReUserOperate::getIsDeleted, ConstantUtils.IS_DELETED_0));
                        if (authCount2 == 0L) {
                            return AjaxResult.error("请勿将文件夹移动到无管理权限的目录下，请联系管理员分配后再试");
                        }
                    }
                }
            }
            if (ConstantUtils.IS_DIRECTORY_FILE_0.equals(fileInfo.getFileIsDirectory())) {
                // 非超级管理员、文件资源管理员，移动文件需要校验权限
                List<String> roleKeyList = SecurityUtils.getLoginUser().getSysRolesList().stream().map(SysRole::getRoleKey).collect(Collectors.toList());
                if (!roleKeyList.contains(RoleConstants.ROLE_KEY_ADMIN) && !roleKeyList.contains(RoleConstants.ROLE_KEY_FILE_RESOURCE_USER)) {
                    long authCount1 = fileReUserOperateService.selectCountFileReUserOperate(new QueryWrapper<FileReUserOperate>().lambda()
                            .eq(FileReUserOperate::getTenantId, SecurityUtils.getTenantId())
                            .eq(FileReUserOperate::getFileId, parentFile.getId())
                            .eq(FileReUserOperate::getUserId, SecurityUtils.getUserId())
                            .eq(FileReUserOperate::getIsDeleted, ConstantUtils.IS_DELETED_0));
                    if (authCount1 == 0L) {
                        //继承权限验证
                        List<String> ancestorsFileIdList = Splitter.on(",").splitToStream(parentFile.getAncestors()).collect(Collectors.toList());
                        Collections.reverse(ancestorsFileIdList);
                        List<FileReUserOperate> fileReUserOperateRetainList = fileReUserOperateMapper.selectGroupPermissionListByUserIdAndFileId(ancestorsFileIdList, String.valueOf(SecurityUtils.getUserId()));
                        for (String fileId : ancestorsFileIdList) {
                            Optional<FileReUserOperate> fileReUserOperateOptional = fileReUserOperateRetainList.stream().filter(fileReUserOperate -> fileId.equals(fileReUserOperate.getFileId().toString())).findFirst();
                            if (fileReUserOperateOptional.isPresent()) {
                                FileReUserOperate fileReUserOperate = fileReUserOperateOptional.get();
                                if (fileReUserOperate.getFileUserAuthCode().equals(ConstantUtils.FILE_AUTH_GROUP_AUTH_MANAGE) || fileReUserOperate.getFileUserAuthCode().equals(ConstantUtils.FILE_AUTH_GROUP_MANAGE)) {

                                } else {
                                    return AjaxResult.error("请勿将文件移动到无管理权限的目录下，请联系管理员分配后再试");
                                }
                            }
                        }
                    } else {
                        List<String> fileUserAuthCodeList = new ArrayList<>();
                        fileUserAuthCodeList.add(ConstantUtils.FILE_AUTH_GROUP_MANAGE);
                        fileUserAuthCodeList.add(ConstantUtils.FILE_AUTH_GROUP_AUTH_MANAGE);
                        long authCount2 = fileReUserOperateService.selectCountFileReUserOperate(new QueryWrapper<FileReUserOperate>().lambda()
                                .eq(FileReUserOperate::getTenantId, SecurityUtils.getTenantId())
                                .eq(FileReUserOperate::getFileId, parentFile.getId())
                                .eq(FileReUserOperate::getUserId, SecurityUtils.getUserId())
                                .in(FileReUserOperate::getFileUserAuthCode, fileUserAuthCodeList)
                                .eq(FileReUserOperate::getIsDeleted, ConstantUtils.IS_DELETED_0));
                        if (authCount2 == 0L) {
                            return AjaxResult.error("请勿将文件移动到无管理权限的目录下，请联系管理员分配后再试");
                        }
                    }
                }
            }
        }
        fileInfoService.doBatchMoveFile(fileParentId, ids);
        return AjaxResult.success();
    }

    @ApiOperation(value = "权限管理")
    @Transactional
    @RequestMapping("/auth/{fileId}")
    @RequiresPermissions(value = {"file:manage:auth", "file:operate:auth"}, logical = Logical.OR)
    public AjaxResult doBatchUserFileAuth(@PathVariable String fileId, @RequestBody List<FileReUserOperate> fileReUserOperateList) {
        if (CollectionUtils.isEmpty(fileReUserOperateList)) {
            return AjaxResult.error();
        }
        fileInfoService.doBatchUserFileAuth(fileId, fileReUserOperateList);
        return AjaxResult.success();
    }

}
