package com.malk.service.teambition;

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

public interface TBClient {

    /**
     * 查询企业项目模板
     * - ppExt:
     * 1. 编辑模板时, 点击左下角"模板信息", 可在请求内看到其ID. 若是需要绑定固定模板ID, 无需通过后端接口获取
     * 2. 另外若是扩展了任务详情加载回调, 通过任务查询 taskId 查询到 project 实际为 editStateProjectId [该字段接口文档有但未返回]
     *
     * @param ptIds 项目模版ID集合，逗号组合
     * @param q     模糊查询名字
     * @apiNote https://open.teambition.com/docs/apis/6321c6d1912d20d3b5a4a30f
     */
    List<Map> templateSearch(String ptIds, String q);

    /**
     * 搜索企业成员: 条件为空返回也为空
     *
     * @param query 用户名、用户拼音、用户名简拼、邮箱、手机号码 [实测 name, email, phone 有效; pinyin, py 无效, 且这两个字段在个人信息页面不透出]
     * @apiNote https://open.teambition.com/help/docs/5eb5431141b191001bcda95c
     */
    @Deprecated
    List<Map> userSearch(String query);

    /**
     * 通过 Teambition 用户 ID 查询钉钉信息
     *
     * @param refer 常见的 refer 类型： dingTalk-corp 钉钉企业 dingTalk-team 钉钉部门 dingTalk-user 钉钉用户
     * @apiNote https://open.teambition.com/docs/apis/6321c6ce912d20d3b5a48e5f
     */
    @Deprecated
    List<Map> idMapQuery(String tbId, String refer, String refId);

    List<Map> idMapQuery(String userId, boolean isTbID);

    /**
     * 更新企业成员
     *
     * @param operatorId 操作人 ID
     * @param members    格式: { userId, role, profile: { name, phone, email, ...} }, 成员角色，-1-外部成员 0-成员 1-管理员 2-拥有者
     * @apiNote https://open.teambition.com/docs/apis/6321c6ce912d20d3b5a48a5b
     */
    Map updateUser(String operatorId, List<Map> members);

    /**
     * 创建空白项目
     */
    Map projectCreate(String name, String operatorId);

    /**
     * 通过模板创建项目
     *
     * @apiNote https://open.teambition.com/docs/apis/6321c6d0912d20d3b5a49753
     */
    Map projectCreateWithTemplate(String name, String templateId, String operatorId);

    /**
     * 查询项目
     *
     * @param projectIds 项目ID集合，逗号分隔
     * @param name       项目名字(模糊匹配)
     * @param sourceId   原始项目ID
     */
    List<Map> projectDetail(String projectIds, String name, String sourceId);

    /**
     * 更新项目 [增量]
     *
     * @param data String name, description, logo, visibility, startDate, endDate [visibility 项目可见性，project | organization]
     */
    Map projectUpdate(String projectId, Map<String, String> data, String operatorId);

    /**
     * 更新项目的项目分组 [ ppExt: 若修改分组相同, 不返回204, 会报错400, 已兼容 ]
     *
     * @apiNote https://open.teambition.com/docs/apis/6321c6d0912d20d3b5a49a5c
     */
    Map updateProjectTag(String projectId, List<String> projectTagIds, String operatorId);

    /**
     * 创建项目成员 [新版本] ppExt: 成员ID不能为空\不能重复, 重复创建会增量更新但不会删除成员
     *
     * @apiNote https://open.teambition.com/docs/apis/6363bcfa912d20d3b56faf07
     */
    List<Map> createProjectMember(String projectId, List<String> userIds, String operatorId);

    /**
     * 获取项目角色列表
     *
     * @return { result:  { level } }   项目角色等级: 0=项目成员, 1=项目管理员, 2=项目拥有者, -3:任务访客
     * @apiNote https://open.teambition.com/docs/apis/6321c6d1912d20d3b5a49b8f
     */
    List<Map> queryProjectRoles(String projectId);

    /**
     * 修改项目成员的角色 ppExt: 新增场景下 userId 可以为钉钉用户ID, 但修改场景下, 需要传递TB用户ID
     *
     * @param roleIds 角色ID列表 [通过 获取项目角色列表 获取]
     * @return { result:  { role } }   项目角色等级: 0=项目成员, 1=项目管理员, 2=项目拥有者, -3:任务访客
     * @apiNote https://open.teambition.com/docs/apis/6321c6d0912d20d3b5a49942
     */
    List<Map> updateProjectMember(List<String> userIds, List<String> roleIds, String projectId);

    /**
     * 获取项目成员列表
     *
     * @apiNote https://open.teambition.com/docs/apis/6321c6d0912d20d3b5a49906
     */
    List<Map> queryProjectMember(String projectId, Map body);

    /**
     * 查询任务详情
     *
     * @param taskId       任务ID集合,使用逗号分隔,和parentTaskId冲突(选其一)
     * @param shortIds     任务短ID集合,使用逗号分隔
     * @param parentTaskId 父任务ID,和taskIds冲突(选其一)
     * @return { priority } 默认排序：“较低”：-10，“普通”：0，“紧急”：1，“非常紧急”：2; 后台调整：调整后按照显示顺序排序，若是新增就会3，4往下。按照 -10，0，1，2，3，4
     * @apiNote https://open.teambition.com/docs/apis/6321c6d2912d20d3b5a4a7b8
     */
    List<Map> queryTaskDetail(String taskId, String shortIds, String parentTaskId);

    /**
     * 搜索任务列表
     *
     * @apiNote https://open.teambition.com/docs/apis/6363bcfb912d20d3b56fb13f
     */
    List<Map> queryTaskGroupList(String projectId, Map param);

    /**
     * 查询项目任务
     *
     * @param param:q ppExt TQL 格式 "cf:项目字段ID" + ORDER BY + AND + OR [不支持小写]
     * @apiNote API: https://open.teambition.com/docs/apis/6321c6d1912d20d3b5a49ec1
     * @apiNote TQL: https://open.teambition.com/docs/documents/639982966b99d5002b510f0b
     */
    List<Map> queryProjectTaskList(String projectId, Map param, QueryAll lambda);

    /**
     * 更新任务截止时间
     *
     * @implNote 204 若是传入dueDate与相同, 则会直接返回204报错, 若原来是年月日, 修改为同一天添加时分秒, 也属于不同时间
     */
    Map updateTaskDueDate(String taskId, String dueDate, String operatorId);

    /**
     * 更新任务执行者 [ppExt: 1. 人员未匹配, 不执行修改; 2. 非项目成员页面上不能添加, 但接口可写入]
     *
     * @apiNote https://open.teambition.com/docs/apis/6321c6d2912d20d3b5a4a63d
     */
    Map updateTaskExecutor(String taskId, String operatorId, String executorId, boolean disableActivity, boolean disableNotification);

    /**
     * 更新任务自定义字段值
     * - ppExt:
     * 1. 自定义字段传入name会自动匹配, 且通过接口更新单行文本也可放入链接
     * 2. 未匹配到返回400; 若是下拉框不在下拉选项也可赋值, 修改后选项消失. 注意name是必填
     *
     * @apiNote https://open.teambition.com/docs/apis/6321c6d2912d20d3b5a4a579
     */
    Map updateTaskCustomField(String taskId, String operatorId, Map body);

    /**
     * 更新任务自定义字段值
     * - ppExt:
     * 1. 自定义字段传入name会自动匹配, 且通过接口更新单行文本也可放入链接
     * 2. 未匹配到返回400; 若是下拉框不在下拉选项也可赋值, 修改后选项消失. 注意name是必填
     *
     * @apiNote https://open.teambition.com/docs/apis/6321c6d2912d20d3b5a4a579
     */
    Map updateTaskFlowStatus(String taskId, String operatorId, String taskflowstatusId, String tfsUpdateNote);

    /**
     * 获取自定义字段 ppExt: 目前原厂还未开放企业级字段, 若同一个项目存在不同项目类型, 建议使用企业字段, 保证ID的唯一性
     *
     * @apiNote https://open.teambition.com/docs/apis/6321c6d0912d20d3b5a497f6
     */
    List<Map> queryProjectCustomField(String projectId, Map body);

    /**
     * 搜索项目工作流状态 [ppExt: 注意不同任务类型名称唯一性, 如通用已完成不要使用]
     *
     * @apiNote https://open.teambition.com/docs/apis/6321c6d1912d20d3b5a4a142
     */
    List<Map> queryProjectCustomFlowStatus(String projectId, Map body);

    /**
     * 搜索项目工作流 [ppExt: 即任务类型]
     *
     * @apiNote https://open.teambition.com/docs/apis/6321c6d1912d20d3b5a49fc3
     */
    List<Map> queryProjectCustomFlow(String projectId, Map body);

    /**
     * 获取依赖项
     *
     * @apiNote https://open.teambition.com/docs/apis/63613a18912d20d3b5296e6d
     */
    List<Map> queryTaskDependency(String taskId, Map body);

    /**
     * 删除任务依赖
     *
     * @apiNote https://open.teambition.com/docs/apis/65e5c202912d20d3b50a63ad
     */
    Map removeTaskDependency(String dependencyId, String operatorId);

    /**
     * 获取项目下甘特图基线
     *
     * @apiNote https://open.teambition.com/docs/apis/6424f885912d20d3b50b759b
     */
    List<Map> queryGanttBaselineList(String projectId, Map body);

    /**
     * 获取甘特图基线下的任务 ppExt: 创建基线时候会记录当时「项目下有开始时间或截止时间的任务」，若没有这样的任务，基线内不会保存 [基线下任务Id, 是相同的, 仅保留了任务标题和时间]
     *
     * @apiNote https://open.teambition.com/docs/apis/6424f857912d20d3b50b048a
     */
    List<Map> queryGanttBaselineTask(String baselineId, Map param, QueryAll lambda);

    /**
     * 查询项目分组 [ppExt: TB分组有继承关系，传递当前最后一层即可]
     *
     * @apiNote https://open.teambition.com/docs/apis/6321c6d1912d20d3b5a4a2c7
     */
    List<Map> queryTagList(Map param);

    /**
     * 修改项目分组
     *
     * @apiNote https://open.teambition.com/docs/apis/6363bcfb912d20d3b56fb36f
     */
    Map updateTag(String projectTagId, Map param);


    /**
     * 查询项目集
     *
     * @apiNote https://open.teambition.com/docs/apis/64e810fe912d20d3b58f9ff9
     */
    List<Map> queryProgramList(String programIds);

    /**
     * 批量添加项目到项目集
     *
     * @apiNote https://open.teambition.com/docs/apis/64e810fe912d20d3b58f9ff9
     */
    List<Map> upsertProgramProject(String programId, List<String> projectIds);

    /**
     * 查询全部数据 [函数回调]
     * - ppExt
     * 1. 若只需查询单页数据, lambda 传入 null 即可
     * 2. 在回调内独立处理每批数据场景, 若是需要等待全部数据查询完再处理场景, 可以定义集合接收
     * 2. 若是在回调内已拿到了符合预期的数据, 可返回 null, 触发递归出口 [布尔值 isAll 状态]
     */
    @FunctionalInterface
    interface QueryAll {
        boolean dataList(List<Map> list);
    }
}