package com.malk.service.dingtalk;

import com.malk.server.dingtalk.DDR_New;

import java.util.List;
import java.util.Map;

public interface DDClient_Storage {


    ///////////////////////// 钉盘附件 /////////////////////////

    /**
     * 新建空间
     *
     * @implSpec 客户端云盘内是不可见: 1. 官方OA审批 - 审批钉盘空间&附件 - 获取审批钉盘空间信息; 2. 文档/文件 - 存储管理 - 空间管理 - 添加空间
     */
    DDR_New createSpaces(String accessToken, String name, String unionId);

    /**
     * 获取空间列表 [钉盘-团队文件-第一层目录列表]
     *
     * @implSpec 忽略分页, 一次性全量查询
     */
    List<Map> getSpaces(String accessToken, String unionId);

    /**
     * 获取文件或文件夹列表
     *
     * @param parentId 父目录Id。根目录时，该参数是0
     * @implSpec 忽略分页, 一次性全量查询; extInfo 非必填参数
     */
    List<Map> getDentries(String accessToken, String unionId, String spaceId, String parentId, Map extInfo);

    /**
     * 添加文件夹 [特殊字符已处理]
     *
     * @param name   文件夹的名称，命名有以下要求：头尾不能包含空格，否则会自动去除; 不能包含特殊字符，包括：制表符、*、"、<、>、|; 不能以"."结尾
     * @param option ppExt: 文件夹名称冲突策略, 返回已存在文件夹, 避免查询文件夹列表  UtilMap.map("conflictStrategy", "RETURN_DENTRY_IF_EXISTS")
     */
    Map addFolders(String accessToken, String unionId, String spaceId, String parentId, String name, Map option);

    ///////////////////////// 知识库 /////////////////////////

    /**
     * 获取知识库列表 [ ppExt: 查询用户有权限的知识库列表, 接口已废弃. 现使用查询接口, 同样会受到权限控制 ]
     *
     * @param operatorId fixme 查询受到 operatorId 权限控制, 仅会返回操作者有权限知识库
     * @apiNote https://open.dingtalk.com/document/orgapp/get-knowledge-base-list
     */
    List<Map> getWorkspaces(String accessToken, String operatorId, Map extInfo);

    /**
     * 搜索知识库 [ ppExt: 知识库列表接口, 查询受到 operatorId 权限控制, 仅会返回操作者有权限知识库 ]
     *
     * @apiNote https://open.dingtalk.com/document/orgapp/search-knowledge-base
     */
    List<Map> searchWorkspaces(String accessToken, String operatorId, String keyword, Map option);

    /**
     * 获取知识库详情
     * ppExt: 若是权限外, 返回 403 无访问权限 [ fixme: 注意创目录接口, 会单独返回 dentryUuid, 返回的 rootNodeId 本质上是 dentryId ]
     * 1. 知识库返回根节点 rootNodeId, 即根目录的 dentryUuid, 可添加整个知识库编辑权限, 通过知识库创建者赋权
     * 2. fixme 知识库列表接口, 查询受到 operatorId 权限控制, 仅会返回操作者有权限知识库;
     * 3. ppExt 特别说明: 知识库 creatorId 就是所有者, 转交后 creatorId 会自动同步更新
     *
     * @param withPermissionRole 仅会返回 operatorId 对应知识库的权限, permissionRole
     * @apiNote https://open.dingtalk.com/document/orgapp/get-knowledge-base
     */
    Map getWorkspaceDetail(String accessToken, String operatorId, String workspaceId, boolean withPermissionRole);

    /**
     * 知识库复制文件或文件夹 [ppExt: 艾为灰度接口, 支持文件夹的复制]
     * fixme: 文件复制后, 变更记录不会保存
     * 1.知识库文件/文件夹复制接口需要传递来源 workplaceId, 但测试下来传递目标 workplaceId 也可以, 包括从我的文档内拷贝均验证通过
     * 2.知识库复制需要同时有文件与\复制目标文件夹下编辑权限. 目前外部使用不能提供公共操作账号, 只能通过 dentryUuid 给来源文件添加编辑权限, 再进行复制操作
     * 3.高密知识库访问限制: 同一个知识库内可以复制, 产品答复通过接口形态也与实际操作一致的表现, 均有控制不能往外进行复制. 写入是被允许的
     * 4. ppExt 设置打断权限后, 若是没有父文件编辑以上权限, 复制异常
     */
    DDR_New copyDentries(String accessToken, String operatorId, String workspaceId, String fileDentryId, String targetSpaceId, String toParentDentryId, String fileName);

    /**
     * 创建知识库文档/文件夹 [ppExt: 文件/文件夹名称若重复会自动添加(1)\(2)\..., 目前通过自建文件夹/文件数据表控制]
     * -
     * [ fixme: 注意创目录接口, 会单独返回 dentryUuid, 返回的 rootNodeId 本质上是 dentryId ]
     *
     * @param name    文件名称 / 文件夹名称
     * @param docType DOC：文字, WORKBOOK：表格, MIND：脑图, FOLDER：文件夹
     * @apiNote https://open.dingtalk.com/document/isvapp/create-team-space-document
     */
    DDR_New createFolder(String accessToken, String operatorId, String workspaceId, String name, String docType, String parentNodeId, Map extInfo);

    /**
     * 查询知识库节点信息
     * ppExt: 历史接口, 可兼容当前TB返回
     * 1. TB 任务上未返回真实 workspaceId, 返回的 WorkspaceId 其实是 spaceId, instanceId 其实是 dentryId.
     * 2. 通过提供 spaceId + dentryId 查询创建人, 再由创建人为公共账号添加编辑权限, 再通过公共账号复制 [ppExt: 知识库可为其他成员添加不高于自身的权限]
     * 3. fixme: 知识库所有操作和权限都与依赖于权限, 通过 spaceId + dentryId 查询创建人需要传递操作者, 操作者需要有查看以上权限
     *
     * @apiNote https://open.dingtalk.com/document/isvapp/query-knowledge-base-node-information?spm=a2q3p.21071111.0.0.93ffaiEWaiEWOI
     */
    DDR_New getSpaceDentryDetail(String accessToken, String operatorId, String spaceId, String dentryId, boolean includeSpace);


    ///////////////////////// 储存管理 /////////////////////////

    /**
     * 搜索文件 [ppExt: 支持知识库 + 文档检索]
     * fixme: 不实用, 虽然可以返回修改权限所依赖的 dentryUuid, 但搜索不支持知识库检索, 且重名文件无法区分
     *
     * @apiNote https://open-dev.dingtalk.com/apiExplorer?spm=ding_open_doc.document.0.0.44862e9ajnDDHC#/?devType=org&api=storage_2.0%23SearchDentries
     */
    List<Map> searchDentry(String accessToken, String operatorId, String keyword, Map option);

    /**
     * 修改权限
     * ppExt: fixme: 若是创建人权限被管理员拿走, 会导致500异常, 需要兼容; 若是创建人赋值编辑权限, 也会是500异常
     * 1. 依赖 dentryUuid, 目前创建文件/文件夹, 复制文件/文件夹, 以及知识库链接 node 后字符串 或者是通过链接反查 nodeId 都是 dentryUuid
     * 2. 知识库复制需要同时有文件与\复制目标文件夹下编辑权限, 知识库可为其他成员添加不高于自身的权限, 可通过反查 dentryUuid 通过创建人添加编辑权限, 再进行复制
     *
     * @param members 权限成员列表，最大size30。[ fixme 可通过 partition 快速切割: List<List<String>> parts = Lists.partition(staffIds, 30);]
     * @param option  duration 目前仅OwnerType为APP的Space支持临时权限
     * @apiNote https://open.dingtalk.com/document/orgapp/modify-permissions-file
     */
    boolean updateDentryPermissions(String accessToken, String dentryUuid, String unionId, String roleId, List<Map> members, Map option);

    /**
     * 删除权限 [ ppExt: 会自动移除更低的权限 ]
     *
     * @apiNote https://open.dingtalk.com/document/orgapp/delete-permissions-file
     */
    boolean deleteDentryPermissions(String accessToken, String dentryUuid, String unionId, String roleId, List<Map> members, Map option);

    /**
     * 设置权限继承模式 [ fixme: 设置打断权限后, 若是没有父文件编辑以上权限, 复制异常 ]
     * ppExt: 设置为打断模式, 与手动修改权限效果一致. 后续知识库成员调整, 非管理者与所有者人员不会传递到当前路径下, 即该文件若要可见需要重新对成员赋权
     *
     * @param inheritance 不支持OWNER和MANAGER的打断, 默认权限继承模式
     *                    BREAK: 打断 权限的传递在当前节点做一个打断;
     *                    PASS_ON: 传递 当前文件(夹)会继承所有父节点的权限, 然后结合当前文件(夹)上的权限, 相同成员权限取最大
     * @apiNote https://open.dingtalk.com/document/orgapp/set-permission-inheritance-mode
     */
    boolean updateDentryPermissionsInheritances(String accessToken, String dentryUuid, String unionId, String inheritance);

    /**
     * 获取权限列表 [ fixme: 需要获取知识库根目录 dentryUuid 成员列表作为权限原始数据 ]
     *
     * @param option 原 option 参数: nextToken: 分页游标, maxResults: 分页大小，默认值30; filterRoleIds: 过滤角色 [ OWNER, MANAGER, EDITOR, DOWNLOADER, READER ]
     * @apiNote https://open.dingtalk.com/document/orgapp/get-permission-list
     */
    List<Map> queryDentryPermissions(String accessToken, String dentryUuid, String unionId, Map option);


    ///////////////////////// OA审批附件 /////////////////////////

    /**
     * 获取审批钉盘空间信息
     *
     * @implNote space_id 说明
     * - 一个企业内审批附件钉盘space_id是唯一的。
     * - 本接口有授权上传权限的作用。每次调用上传附件API接口前，建议使用上传操作人userId再调用一次本接口。
     * - 审批附件钉盘，属于企业钉盘的一部分，占用的是企业钉盘空间，但是审批附件钉盘空间和其中的文件在客户端内是不可见的。
     */
    String getSpacesInfos(String access_token, String userId, String agentId);

    /**
     * 添加权限
     *
     * @param dentryId 文件或者文件夹Id。说明: 如果对整个空间授权，该参数值传0
     * @param roleId   权限角色Id。 OWNER：拥有者, MANAGER：管理者, EDITOR：编辑者, DOWNLOADER：下载者, READER：查看者
     * @param members  权限成员列表，最大值30。[配置详见文档]
     */
    boolean addSpacePermissions(String access_token, String spaceId, String dentryId, String unionId, String roleId, List<Map> members, Map option);

    ///////////////////////// 通用上传逻辑 /////////////////////////

    /**
     * 获取文件上传信息
     *
     * @implNote protocol 通过指定上传协议返回不同协议上传所需要的信息。HEADER_SIGNATURE：Header加签
     * @implNote multipart 是否需要分片上传。 true：需要; false：不需要. 说明: 5G以下文件，设为false，简化上传步骤。
     * 5G以上文件，必须设为true，否则会上传失败。
     */
    DDR_New getUploadInfos(String access_token, String spaceId, String unionId, Map option);

    /**
     * 文件上传
     *
     * @return uploadKey: 上传唯一标识; headerSignatureInfo: { resourceUrls: 多个上传下载URL列表, headers: 请求头信息 }
     */
    boolean uploadFiles(String resourceUrl, Map<String, String> headerSignatureInfo, String pathFile);

    /**
     * 提交文件
     *
     * @param name     文件的名称，带后缀 [注意命名规范]
     * @param parentId 父目录Id。根目录时，该参数是0。
     */
    Map commitFiles(String access_token, String spaceId, String unionId, String uploadKey, String name, String parentId, Map option);
}
