package cn.axzo.workflow.starter.api;

import cn.axzo.workflow.starter.feign.ext.WorkflowEngineStarterFeignConfiguration;
import cn.axzo.workflow.common.util.ThreadUtil;
import cn.axzo.workflow.client.annotation.WorkflowEngineFeignClient;
import cn.axzo.workflow.common.annotation.InvokeMode;
import cn.axzo.workflow.common.annotation.Manageable;
import cn.axzo.workflow.common.model.dto.print.PrintFieldDTO;
import cn.axzo.workflow.common.model.request.bpmn.print.PrintFieldQueryDTO;
import cn.azxo.framework.common.model.CommonResponse;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.validation.annotation.Validated;
import javax.validation.constraints.NotBlank;
import java.util.List;
import java.util.Map;
import cn.axzo.workflow.common.model.request.admin.ProcessAdminCreateDTO;
import cn.axzo.workflow.common.model.request.admin.ProcessAdminDeleteDTO;
import cn.axzo.workflow.common.model.request.admin.ProcessAdminQueryDTO;
import cn.axzo.workflow.common.model.response.admin.ProcessAdminVo;
import cn.axzo.workflow.common.model.request.bpmn.activity.BpmnActivityTimeoutCallbackDTO;
import cn.axzo.workflow.common.model.request.bpmn.activity.BpmnActivityTimeoutTriggerDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnActivitySetAssigneeDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnActivityTriggerDTO;
import cn.axzo.workflow.common.model.request.form.definition.StartFormSearchDTO;
import cn.axzo.workflow.common.model.request.form.instance.FormDetailDTO;
import cn.axzo.workflow.common.model.request.form.instance.FormSearchDTO;
import cn.axzo.workflow.common.model.response.form.FormVO;
import cn.axzo.workflow.common.model.response.form.definition.FormDefinitionVO;
import cn.axzo.workflow.common.model.response.form.instance.FormInstanceVO;
import cn.axzo.workflow.common.model.request.es.InstanceSearchReqDTO;
import cn.axzo.workflow.common.model.response.BpmPageResult;
import cn.axzo.workflow.common.model.response.es.ProcessInstanceDocumentVO;
import cn.axzo.workflow.common.model.dto.SignFileDTO;
import cn.axzo.workflow.common.model.dto.SimpleDocDTO;
import cn.axzo.workflow.common.model.request.bpmn.log.LogApproveSearchDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BeforeProcessInstanceCreateDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceAbortDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceAdminPageReqVO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCancelDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCarbonCopyDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCheckApproverDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCreateDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceLogQueryDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceMyPageReqVO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceQueryDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.SuperBpmnProcessInstanceCancelDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.doc.ApproverReadStatusDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.doc.ChangeApproverReadStatusDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.doc.ProcessDocQueryDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskButtonSearchDTO;
import cn.axzo.workflow.common.model.request.form.instance.FormVariablesUpdateDTO;
import cn.axzo.workflow.common.model.response.bpmn.BatchOperationResultVO;
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceAdminPageItemVO;
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceLogVO;
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstancePageItemVO;
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceVO;
import cn.axzo.workflow.common.model.response.bpmn.process.ExtProcessLogVO;
import cn.axzo.workflow.common.model.response.bpmn.process.NodesByModelVO;
import cn.axzo.workflow.common.model.response.bpmn.process.ProcessNodeDetailVO;
import cn.axzo.workflow.common.model.response.bpmn.process.doc.DocPendingVO;
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskButtonVo;
import com.fasterxml.jackson.databind.node.ObjectNode;
import javax.annotation.Nullable;
import javax.validation.constraints.NotNull;
import cn.axzo.workflow.common.model.request.category.*;
import cn.axzo.workflow.common.model.response.category.CategoryConfigItemVO;
import cn.axzo.workflow.common.model.response.category.CategoryGroupVarItemVo;
import cn.axzo.workflow.common.model.response.category.CategoryItemVO;
import org.springframework.web.bind.annotation.*;
import static cn.axzo.workflow.common.enums.RpcInvokeModeEnum.*;
import cn.axzo.workflow.common.model.request.bpmn.BpmnButtonMetaInfo;
import cn.axzo.workflow.common.model.request.bpmn.model.BpmnModelCreateDTO;
import cn.axzo.workflow.common.model.request.bpmn.model.BpmnModelSearchDTO;
import cn.axzo.workflow.common.model.request.bpmn.model.BpmnModelUpdateDTO;
import cn.axzo.workflow.common.model.request.bpmn.model.doc.DocByIdDTO;
import cn.axzo.workflow.common.model.request.bpmn.model.doc.DocCreateDTO;
import cn.axzo.workflow.common.model.request.bpmn.model.doc.DocOrderDTO;
import cn.axzo.workflow.common.model.request.bpmn.model.doc.DocQueryDTO;
import cn.axzo.workflow.common.model.request.bpmn.model.doc.DocResetDTO;
import cn.axzo.workflow.common.model.request.bpmn.model.doc.DocSearchDTO;
import cn.axzo.workflow.common.model.request.bpmn.model.doc.DocStatusDTO;
import cn.axzo.workflow.common.model.request.bpmn.model.doc.DocTenantQueryDTO;
import cn.axzo.workflow.common.model.request.bpmn.model.doc.DocUpdateDTO;
import cn.axzo.workflow.common.model.request.bpmn.print.PrintTemplateConfigQueryDTO;
import cn.axzo.workflow.common.model.request.bpmn.print.PrintTemplateConfigUpsertDTO;
import cn.axzo.workflow.common.model.request.bpmn.print.RestPrintTemplateConfigDTO;
import cn.axzo.workflow.common.model.response.bpmn.model.BpmnModelDetailVO;
import cn.axzo.workflow.common.model.response.bpmn.model.BpmnModelExtVO;
import cn.axzo.workflow.common.model.response.bpmn.model.doc.DocBaseVO;
import cn.axzo.workflow.common.model.response.print.PrintModelDTO;
import cn.axzo.workflow.common.model.request.bpmn.RestBpmnProcessVariable;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnNodeBackSystemOperateDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnOptionalNodeDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnRobotTaskCompleteDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnRobotTaskCreateDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskAttachmentDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskAuditDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskAuditWithFormDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskBackAuditDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskCommentDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskCountersignDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskPageSearchDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskRemindDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskResetApproversDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskTransferDTO;
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnHistoricTaskInstanceGroupVO;
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnHistoricTaskInstanceVO;
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskDonePageItemVO;
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskInstanceVO;
import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskTodoPageItemVO;
import javax.validation.constraints.NotEmpty;
import cn.axzo.workflow.common.model.request.bpmn.definition.BpmnProcessDefinitionUpdateDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessDefinitionPageDTO;
import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessDefinitionVO;
import static cn.axzo.workflow.common.constant.BpmnConstants.NO_TENANT_ID;

/**
 * Workflow Engine Starter Management Service
 * <p>
 * 该类是根据 API 动态生成，不同版本可能会开放新的接口，或回收一些旧接口
 * <p>
 * Auto generation by workflow engine, It cannot be manually modified
 */
@org.springframework.cloud.openfeign.FeignClient(name = "workflow-engine", url = "${axzo.service.workflow-engine:http://workflow-engine:8080}", configuration = WorkflowEngineStarterFeignConfiguration.class)
public interface WorkflowManageService {

    @Operation(summary = "查询指定审批流程是否能打印，打印开关是否开启，是否存在打印模板")
    @GetMapping("/api/print/admin/template/exists")
    @InvokeMode(SYNC)
    Boolean hasPrintTemplate(@NotBlank(message = "流程实例不能为空") @RequestParam String processInstanceId);

    @Operation(summary = "获取打印模板中可打印的字段")
    @PostMapping("/api/print/admin/fields")
    @InvokeMode(SYNC)
    List<PrintFieldDTO> getPrintFields(@Validated @RequestBody PrintFieldQueryDTO dto);

    @Operation(summary = "获取指定流程下用于替换打印的相关变量")
    @GetMapping("/api/print/admin/field/variables")
    @InvokeMode(SYNC)
    Map<String, Object> getPrintFieldVariables(@NotBlank(message = "流程实例不能为空") @RequestParam String processInstanceId);

    /**
     * 查询管理员
     * @param dto 管理员数据
     * @return 管理员id
     */
    @PostMapping("/api/process/admin/query")
    @InvokeMode(SYNC)
    List<ProcessAdminVo> queryProcessAdmins(@RequestBody ProcessAdminQueryDTO dto);

    /**
     * 查询管理员
     * @param dto 管理员数据
     * @return 管理员id
     */
    @PostMapping("/api/process/admin/query/count")
    @InvokeMode(SYNC)
    Integer queryProcessAdminsCount(@RequestBody ProcessAdminQueryDTO dto);

    /**
     * 添加管理员
     * @param dto 管理员数据
     * @return 管理员id
     */
    @PostMapping("/api/process/admin/create")
    @InvokeMode(SYNC)
    Long createProcessAdmin(@RequestBody ProcessAdminCreateDTO dto);

    /**
     * 批量添加管理员
     * @param dtos
     * @return
     */
    @PostMapping("/api/process/admin/batch/create")
    @InvokeMode(SYNC)
    Void batchCreateProcessAdmin(@RequestBody List<ProcessAdminCreateDTO> dtos);

    /**
     * 删除管理员
     * @param id 配置表id
     * @return
     */
    @DeleteMapping("/api/process/admin/delete")
    @InvokeMode(SYNC)
    Integer deleteCommonProcessAdmin(@RequestParam Long id);

    /**
     * 根据条件删除管理员
     * @param dto 删除条件
     * @return
     */
    @DeleteMapping("/api/process/admin/delete/criteria")
    @InvokeMode(SYNC)
    Integer deleteProcessAdminCriteria(@RequestBody ProcessAdminDeleteDTO dto);

    /**
     * 删除管理员
     * @param ids 管理员配置id列表
     * @return
     */
    @DeleteMapping("/api/process/admin/batch/delete")
    @InvokeMode(SYNC)
    Integer batchDeleteProcessAdmin(@RequestBody List<Long> ids);

    @PostMapping("/api/form/admin/form/page")
    @InvokeMode(SYNC)
    @Manageable
    List<FormVO> formPage(@Validated @RequestBody FormSearchDTO dto);

    /**
     * 从 ES 中搜索符合条件的实例纬度数据
     *
     * @param dto
     * @return
     */
    @PostMapping("/api/es/instance/search")
    @InvokeMode(SYNC)
    BpmPageResult<ProcessInstanceDocumentVO> searchInstanceInEs(@Validated @RequestBody InstanceSearchReqDTO dto);

    @DeleteMapping("/api/process/instance/super/cancel")
    @Manageable
    Boolean superCancelProcessInstance(@Validated @RequestBody SuperBpmnProcessInstanceCancelDTO dto);

    /**
     * 抄送流程实例（未实现）
     *
     * @param dto
     * @return
     */
    @Operation(summary = "抄送流程实例")
    @PostMapping("/api/process/instance/carbon-copy")
    @Deprecated
    @Manageable
    Boolean carbonCopyProcessInstance(@Validated @RequestBody BpmnProcessInstanceCarbonCopyDTO dto);

    /**
     * 查询所有的审批流
     *
     * @return
     */
    @Operation(summary = "查询所有的审批流")
    @PostMapping("/api/process/instance/page/all")
    @Manageable
    @InvokeMode(SYNC)
    BpmPageResult<BpmnProcessInstanceAdminPageItemVO> getAllProcessInstancePage(@Validated @RequestBody BpmnProcessInstanceAdminPageReqVO dto);

    /**
     * 我发起的审批列表
     */
    @Operation(summary = "我发起的审批列表")
    @PostMapping("/api/process/instance/page/my")
    @Manageable
    @InvokeMode(SYNC)
    BpmPageResult<BpmnProcessInstancePageItemVO> getMyProcessInstancePage(@Validated @RequestBody BpmnProcessInstanceMyPageReqVO dto);

    /**
     * 更新流程定义的状态
     *
     * @param processDefinitionId 流程定义的编号
     * @param status              1, "active"; 2, "suspended"
     */
    @Operation(summary = "更新指定流程定义的版本的状态, 处于 suspended 状态的流程模型将不能再发起实例")
    @PutMapping("/api/process/instance/status/update")
    @Manageable
    @InvokeMode(SYNC)
    Boolean updateProcessStatus(@NotBlank(message = "流程定义 ID 不能为空") @RequestParam String processDefinitionId, @NotNull(message = "状态不能为空") @RequestParam Integer status);

    /**
     * 获取审批流程实例的运行图
     *
     * @param processInstanceId
     * @param tenantId
     * @return
     */
    @Operation(summary = "获取审批流程实例的运行图")
    @GetMapping("/api/process/instance/graphical")
    @Manageable
    @InvokeMode(SYNC)
    ObjectNode processInstanceGraphical(@NotBlank(message = "流程实例 ID 不能为空") @RequestParam String processInstanceId, @Nullable @RequestParam(required = false) String tenantId);

    /**
     * 推断指定流程实例的所有节点执行顺序
     *
     * @return
     */
    @Operation(summary = "推断指定流程实例的所有节点执行顺序")
    @GetMapping("/api/process/instance/node/forecasting")
    @Manageable
    @InvokeMode(SYNC)
    List<ProcessNodeDetailVO> processInstanceNodeForecast(@NotBlank(message = "流程实例 ID 不能为空") @RequestParam(required = false) String processInstanceId, @Nullable @RequestParam(required = false) String tenantId);

    /**
     * 推断指定流程实例的过滤掉部分节点执行顺序
     *
     * @param allNode 如果为真时,相当于调用 {@link ProcessInstanceApi#processInstanceNodeForecast(String, String)} 方法,切会直接丢弃 nodeDefinitionKeys 参数
     *                如果为假时,才结合 nodeDefinitionKeys 过滤掉传入的节点
     * @return
     */
    @Operation(summary = "推断指定流程实例的过滤掉部分节点执行顺序")
    @GetMapping("/api/process/instance/node/filter/forecasting")
    @Manageable
    @InvokeMode(SYNC)
    List<ProcessNodeDetailVO> processInstanceFilterNodeForecast(@NotBlank(message = "流程实例 ID 不能为空") @RequestParam(required = false) String processInstanceId, @Nullable @RequestParam(required = false) String tenantId, @RequestParam(required = false, defaultValue = "false") Boolean allNode, @Nullable @RequestParam(required = false) List<String> nodeDefinitionKeys);

    /**
     * 查询实例的租户集合
     *
     * @return
     */
    @Operation(summary = "查询实例的租户集合")
    @GetMapping("/api/process/instance/tenant/ids")
    @Manageable
    @InvokeMode(SYNC)
    List<String> getTenantIds();

    /**
     * 查询 ExtAxProcessLog 表中审批人的冗余信息
     *
     * @param dto
     * @return
     */
    @Operation(summary = "查询 ExtAxProcessLog 表中审批人的冗余信息")
    @GetMapping("/api/process/instance/log/approve/ext")
    @Manageable
    @InvokeMode(SYNC)
    List<ExtProcessLogVO> getProcessLogByInstanceIdAndPersonId(@Validated @RequestBody LogApproveSearchDTO dto);

    /**
     * 将死信队列中的任务转移到正常 JOB 队列中
     * <p>
     * 入参是二选一：当只有 jobId 时，仅将指定的 JOB 转移到正常的队列中；
     * 而传入的是具体的实例 ID，那么会将这个流程下的所有在死信队列中的任务都转移到正常的队列中
     *
     * @param jobId      具体的 JOB ID
     * @param procInstId 具体的实例 ID
     * @return
     */
    @GetMapping("/api/process/job/dead-letter/resume")
    @Manageable
    Void executeDeadLetterJobAction(@RequestParam(required = false) String jobId, @RequestParam(required = false) String procInstId);

    /**
     * 查询死信消息数据
     * @param procInstId 流程实例id
     * @return
     */
    @GetMapping("/dead-letter/exception/stacktrace")
    @Manageable
    String getDeadLetterJobExceptionStacktrace(@RequestParam String procInstId);

    /**
     * 查询死信消息数据
     * @param jobId 死信job的id
     * @return
     */
    @GetMapping("/dead-letter/exception/stacktrace/byId")
    @Manageable
    String getDeadLetterJobExceptionStacktraceByJobId(@RequestParam String jobId);

    /**
     * 获取指定业务分类
     *
     * @return
     */
    @GetMapping("/api/process/category/get")
    @InvokeMode(SYNC)
    CategoryItemVO get(@RequestParam Long id);

    /**
     * 获取指定业务分类集合
     *
     * @param ids
     * @return
     */
    @GetMapping("/api/process/category/getByIds")
    @InvokeMode(SYNC)
    List<CategoryItemVO> getByIds(@RequestParam List<Long> ids);

    /**
     * 获取指定业务分类集合
     *
     * @param values
     * @return
     */
    @GetMapping("/api/process/category/getByValues")
    @InvokeMode(SYNC)
    List<CategoryItemVO> getByValues(@RequestParam List<String> values);

    /**
     * 新增业务分类
     *
     * @return
     */
    @PostMapping("/api/process/category/create")
    @InvokeMode(SYNC)
    CategoryItemVO create(@Validated @RequestBody CategoryCreateDTO req);

    /**
     * 更新业务分类
     *
     * @return
     */
    @PutMapping("/api/process/category/update")
    @InvokeMode(SYNC)
    CategoryItemVO update(@Validated @RequestBody CategoryUpdateDTO dto);

    /**
     * 删除指定业务分类
     *
     * @param id
     * @return
     */
    @DeleteMapping("/api/process/category/delete")
    @InvokeMode(SYNC)
    Boolean delete(@RequestParam Long id);

    /**
     * 更新指定分类状态
     *
     * @param id
     * @param state
     * @return
     */
    @PutMapping("/api/process/category/update/state")
    @InvokeMode(SYNC)
    Boolean updateState(@RequestParam Long id, @RequestParam Boolean state);

    /**
     * 获取指定业务分类集合
     *
     * @return
     */
    @PostMapping("/api/process/category/list")
    @InvokeMode(SYNC)
    List<CategoryItemVO> list(@RequestBody CategorySearchDTO dto);

    /**
     * 搜索业务分类
     *
     * @return
     */
    @PostMapping("/api/process/category/page/search")
    @InvokeMode(SYNC)
    BpmPageResult<CategoryItemVO> search(@RequestBody CategorySearchDTO dto);

    /**
     * 业务分类创建黑白名单配置项
     *
     * @param dto
     * @return
     */
    @PostMapping("/api/process/category/config/create")
    @InvokeMode(SYNC)
    Boolean createConfig(@RequestBody CategoryConfigCreateDTO dto);

    /**
     * 删除指定分类的配置项数据
     *
     * @param id
     * @return
     */
    @DeleteMapping("/api/process/category/config/delete/{id}")
    @InvokeMode(SYNC)
    Boolean deleteConfig(@PathVariable Long id);

    /**
     * 业务分类黑白名单查询
     *
     * @return
     */
    @PostMapping("/api/process/category/config/page/search")
    @InvokeMode(SYNC)
    BpmPageResult<CategoryConfigItemVO> configSearch(@RequestBody CategoryConfigSearchDTO dto);

    /**
     * 更新业务分类的配置类型
     *
     * @param id
     * @param configType
     * @return
     */
    @PostMapping("/api/process/category/config/type/update")
    @InvokeMode(SYNC)
    Boolean updateCategoryConfigType(@RequestParam Long id, @RequestParam String configType);

    /**
     * 用于业务方判断指定的业务分类的黑白名单配置
     *
     * @param tenantId     租户ID
     * @param categoryCode 业务分类编码
     * @return true: 可以发起创建流程实例, false: 不可用
     */
    @GetMapping("/api/process/category/check/status")
    @InvokeMode(SYNC)
    Boolean checkCategoryStatus(@RequestParam Long tenantId, @RequestParam String categoryCode);

    /**
     * 查询分类对应的分组以及分组下的变量
     * @param dto 请求参数
     * @return 分组以及分组下的变量
     */
    @PostMapping("/api/process/category/group-with-vars/list")
    @InvokeMode(SYNC)
    List<CategoryGroupVarItemVo> searchCategoryGroupAndVars(@Validated @RequestBody CategoryGroupVarSearchDto dto);

    /**
     * 新增或者更新分组或者变量
     * @param dto 请求参数
     * @return 是否成功
     */
    @PostMapping("/api/process/category/group-with-vars/upsert")
    Boolean upsertCategoryGroupAndVars(@Validated @RequestBody CategoryGroupVarUpsertDto dto);

    /**
     * 获取流程操作按钮列表
     *
     * @return 流程操作按钮列表
     */
    @GetMapping("/api/process/config/button/list")
    @InvokeMode(SYNC)
    List<BpmnButtonMetaInfo> getDefaultButtons();

    /**
     * 流程模型列表
     *
     * @param dto
     * @return
     */
    @Operation(summary = "流程模型列表")
    @GetMapping("/api/process/model/page")
    @InvokeMode(SYNC)
    BpmPageResult<BpmnModelDetailVO> page(@Validated @RequestBody BpmnModelSearchDTO dto);

    /**
     * 创建流程,
     * return modelId的主键
     */
    @Operation(summary = "创建流程模型")
    @PostMapping("/api/process/model/create")
    @InvokeMode(SYNC)
    String create(@Validated @RequestBody BpmnModelCreateDTO dto);

    /**
     * 通过模型 ID 获取模型
     */
    @Operation(summary = "通过模型ID查询指定流程模型")
    @GetMapping("/api/process/model/get")
    @InvokeMode(SYNC)
    BpmnModelDetailVO getById(@NotBlank(message = "流程模型 ID 不能为空") @RequestParam(required = false) String processModelId, @RequestParam(required = false) String tenantId);

    /**
     * 通过模型 KEY 获取模型
     */
    @Operation(summary = "通过模型KEY查询指定流程模型")
    @GetMapping("/api/process/model/getByKey")
    @InvokeMode(SYNC)
    BpmnModelDetailVO getByKey(@NotBlank(message = "流程模型 KEY 不能为空") @RequestParam(required = false) String processModelKey, @NotBlank(message = "租户不能为空") @RequestParam(required = false) String tenantId);

    /**
     * 校验是否能更新模型即其关联的流程定义内容
     * <p>
     * 偏向业务的接口,flowable 引擎是站在流程定义维度进行激活和挂起
     *
     * @return true 能更新,表明该模型关联的所有定义版本都是挂起状态
     */
    @Operation(summary = "获取指定模型的扩展属性")
    @GetMapping("/api/process/model/ext")
    @InvokeMode(SYNC)
    BpmnModelExtVO getModelExt(@NotBlank(message = "模型 ID 不能为空") @RequestParam(required = false) String modelId);

    /**
     * 修改流程信息
     */
    @Operation(summary = "更新流程模型")
    @PutMapping("/api/process/model/update")
    @InvokeMode(SYNC)
    String update(@RequestBody BpmnModelUpdateDTO dto);

    /**
     * 通过模型 ID 部署模型
     *
     * @return 部署完成的流程定义Id
     */
    @Operation(summary = "通过模型 ID 部署流程模型")
    @PostMapping("/api/process/model/deploy")
    @InvokeMode(SYNC)
    String deployById(@NotBlank(message = "流程模型 ID 不能为空") @RequestParam(required = false) String processModelId, @RequestParam(required = false, defaultValue = "") String modelTenantId, @RequestParam(required = false) String operator);

    /**
     * 通过模型 KEY 部署模型
     *
     * @return 部署完成的流程定义Id
     */
    @Operation(summary = "通过模型 KEY 部署流程模型")
    @PostMapping("/api/process/model/deployByKey")
    @InvokeMode(SYNC)
    String deployByKey(@NotBlank(message = "流程模型 KEY 不能为空") @RequestParam(required = false) String processModelKey, @NotBlank(message = "租户不能为空") @RequestParam(required = false) String modelTenantId, @RequestParam(required = false) String operator);

    /**
     * 通过模型 ID 取消部署流程模型
     *
     * @param processModelId
     * @param tenantId
     * @param operator
     * @return
     */
    @Operation(summary = "通过模型 ID 取消部署流程模型")
    @PostMapping("/api/process/model/undeploy")
    @InvokeMode(SYNC)
    Void unDeployById(@NotBlank(message = "流程模型 ID 不能为空") @RequestParam(required = false) String processModelId, @RequestParam(required = false, defaultValue = "") String tenantId, @RequestParam(required = false) String operator);

    /**
     * 通过模型 ID 删除模型
     */
    @Operation(summary = "删除指定模型 ID 的流程模型")
    @DeleteMapping("/api/process/model/delete")
    @InvokeMode(SYNC)
    Void deleteById(@NotBlank(message = "流程模型 ID 不能为空") @RequestParam String processModelId, @RequestParam(required = false, defaultValue = "") String tenantId);

    /**
     * 通过模型 KEY 删除模型
     *
     * @param processModelKey
     * @param tenantId
     * @return
     */
    @Operation(summary = "删除指定模型 KEY 的流程模型")
    @DeleteMapping("/api/process/model/deleteByKey")
    @InvokeMode(SYNC)
    Void deleteByKey(@NotBlank(message = "流程模型 KEY 不能为空") @RequestParam String processModelKey, @RequestParam(required = false, defaultValue = "") String tenantId);

    /**
     * 通过模型 ID 修改模型状态
     *
     * @param modelId
     * @param status
     * @param operator
     * @return
     */
    @Operation(summary = "修改模型状态")
    @PostMapping("/api/process/model/changeStatus")
    @InvokeMode(SYNC)
    Boolean changeStatus(@NotBlank(message = "模型 ID 不能为空") @RequestParam String modelId, @NotNull(message = "状态不能为空") @RequestParam Integer status, @RequestParam(required = false) String operator);

    /**
     * 修改模型打印开关状态
     *
     * @param modelId
     * @param status
     * @param operator
     * @return
     */
    @Operation(summary = "修改模型打印开关状态")
    @PostMapping("/api/process/model/print/changeStatus")
    @InvokeMode(SYNC)
    Boolean changePrintStatus(@NotBlank(message = "模型 ID 不能为空") @RequestParam String modelId, @NotNull(message = "状态不能为空") @RequestParam Integer status, @RequestParam(required = false) String operator);

    /**
     * 查询流程模型使用的分类列表
     *
     * @return
     */
    @Operation(summary = "查询流程模型使用的分类列表")
    @GetMapping("/api/process/model/category/ids")
    @InvokeMode(SYNC)
    List<String> getModelCategoryList();

    /**
     * 查询模型的租户集合
     *
     * @return
     */
    @Operation(summary = "查询模型的租户集合")
    @GetMapping("/api/process/model/tenant/ids")
    @InvokeMode(SYNC)
    List<String> getModelTenantIds();

    /**
     * 打印模板配置内容更新保存
     *
     * @param dto
     * @return
     */
    @Operation(summary = "打印模板配置内容更新保存")
    @PostMapping("/api/process/model/print/template/upsert")
    @InvokeMode(SYNC)
    Void printTemplateConfig(@Validated @RequestBody PrintTemplateConfigUpsertDTO dto);

    /**
     * 获取打印模板配置内容
     *
     * @param dto
     * @return
     */
    @Operation(summary = "获取打印模板配置内容")
    @PostMapping("/api/process/model/print/template/config/query")
    @InvokeMode(SYNC)
    PrintModelDTO getPrintTemplateConfig(@Validated @RequestBody PrintTemplateConfigQueryDTO dto);

    /**
     * 代运营充值的打印模板
     *
     * @param dto
     * @return
     */
    @Operation(summary = "代运营重置打印模板")
    @PostMapping(value = "/api/process/model/print/template/config/reset")
    @InvokeMode(SYNC)
    Boolean resetPrintTemplateConfig(@Validated @RequestBody RestPrintTemplateConfigDTO dto);

    /**
     * 搜索文档列表
     *
     * @param dto
     * @return
     */
    @Operation(summary = "搜索文档列表")
    @PostMapping(value = "/api/process/model/doc/page")
    @InvokeMode(SYNC)
    BpmPageResult<DocBaseVO> docPage(@Validated @RequestBody DocSearchDTO dto);

    /**
     * 获取指定 docIds 文档列表
     *
     * @return
     */
    @Operation(summary = "获取指定 docIds 文档列表")
    @PostMapping(value = "/api/process/model/doc/ids")
    @InvokeMode(SYNC)
    List<DocBaseVO> docByIds(@Validated @RequestBody DocByIdDTO dto);

    /**
     * 获取指定模板的原始文档列表
     *
     * @param dto
     * @return
     */
    @Operation(summary = "根据业务 ID 获取模型文档列表，自动适配公共模板和代运营")
    @PostMapping(value = "/api/process/model/doc/list")
    @InvokeMode(SYNC)
    List<DocBaseVO> docList(@Validated @RequestBody DocQueryDTO dto);

    /**
     * 获取关联 HiPrint 类型文档模板内容
     *
     * @param fileRelationId
     * @return
     */
    @Operation(summary = "获取关联 HiPrint 类型文档模板内容")
    @PostMapping(value = "/api/process/model/hi-print/content/get")
    @InvokeMode(SYNC)
    String getHiPrintContent(@RequestParam String fileRelationId);

    /**
     * 添加关联文档
     *
     * @return
     */
    @Operation(summary = "添加关联文档")
    @PutMapping(value = "/api/process/model/doc/create")
    @InvokeMode(SYNC)
    Boolean createDoc(@Validated @RequestBody DocCreateDTO dto);

    /**
     * 修改关联文档
     *
     * @return
     */
    @Operation(summary = "修改关联文档")
    @PostMapping(value = "/api/process/model/doc/update")
    @InvokeMode(SYNC)
    Boolean updateDoc(@Validated @RequestBody DocUpdateDTO dto);

    /**
     * 克隆关联文档
     *
     * @param docId
     * @return
     */
    @Operation(summary = "克隆关联文档")
    @PostMapping(value = "/api/process/model/doc/clone")
    @InvokeMode(SYNC)
    Boolean cloneDoc(@RequestParam("id") Long docId);

    /**
     * 删除关联文档
     *
     * @return
     */
    @Operation(summary = "删除指定文档")
    @DeleteMapping(value = "/api/process/model/doc/delete")
    @InvokeMode(SYNC)
    Boolean deleteDoc(@RequestParam("id") Long docId);

    /**
     * 关联文档配置排序
     *
     * @param dto
     * @return
     */
    @Operation(summary = "关联文档配置排序")
    @PostMapping(value = "/api/process/model/doc/order")
    @InvokeMode(SYNC)
    Boolean orderDoc(@Validated @RequestBody DocOrderDTO dto);

    /**
     * 重置关联文档
     *
     * @param dto
     * @return
     */
    @Operation(summary = "重置关联文档配置")
    @PostMapping(value = "/api/process/model/doc/reset")
    @InvokeMode(SYNC)
    Boolean resetDoc(@Validated @RequestBody DocResetDTO dto);

    /**
     * 设置关联文档的停启用状态
     *
     * @param dto
     * @return
     */
    @Operation(summary = "设置关联文档的停启用状态")
    @PostMapping(value = "/api/process/model/doc/status")
    @InvokeMode(SYNC)
    Boolean statusDoc(@Validated @RequestBody DocStatusDTO dto);

    /**
     * 设置关联文档的必选状态
     *
     * @return
     */
    @Operation(summary = "设置关联文档的必选状态")
    @PostMapping(value = "/api/process/model/doc/require")
    @InvokeMode(SYNC)
    Boolean requireDoc(@Validated @RequestBody DocStatusDTO dto);

    /**
     * 特殊的查询设置过关联过文档的工作台 ID 集合
     *
     * @return
     */
    @Operation(summary = "特殊的查询设置过关联过文档的工作台 ID 集合")
    @PostMapping(value = "/api/process/model/has/docs/tenantId")
    @InvokeMode(SYNC)
    List<Long> hasFilesTenantIds(@Validated @RequestBody DocTenantQueryDTO dto);

    /**
     * 为指定流程新增变量
     */
    @PostMapping("/api/process/variable/create/{executionId}")
    @InvokeMode(SYNC)
    Void createVariable(@PathVariable @NotBlank(message = "流程实例 ID 不能为空") String executionId, @RequestBody @Validated RestBpmnProcessVariable restVariable);

    /**
     * 仅更新流程已存在的变量
     *
     * @param executionId
     * @param restVariable
     * @return
     */
    @PostMapping("/api/process/variable/update/{executionId}")
    @InvokeMode(SYNC)
    Void updateVariable(@PathVariable @NotBlank(message = "流程实例 ID 不能为空") String executionId, @RequestBody @Validated RestBpmnProcessVariable restVariable);

    /**
     * 批量删除流程变量
     */
    @DeleteMapping("/api/process/variable/delete/{executionId}")
    @InvokeMode(SYNC)
    Void deleteVariables(@PathVariable("executionId") String executionId, @RequestParam String variableNames, @RequestParam(value = "scope", required = false) String scope);

    /**
     * 用于系统内部操作，跳转到指定节点
     *
     * @param dto 请求参数
     * @return 是否成功
     */
    @Operation(summary = "系统操作回退任务到指定节点")
    @PostMapping("/api/process/task/system/back")
    @Manageable
    Boolean systemBackTask(@Validated @RequestBody BpmnNodeBackSystemOperateDTO dto);

    /**
     * 添加附件
     *
     * @param dto
     * @return
     */
    @Operation(summary = "添加附件")
    @PostMapping("/api/process/task/attachment")
    @Manageable
    Void addAttachment(@Validated @RequestBody BpmnTaskAttachmentDTO dto);

    /**
     * 待审核列表
     */
    @Operation(summary = "待审核列表")
    @GetMapping("/api/process/task/page/todo")
    @Manageable
    @InvokeMode(SYNC)
    BpmPageResult<BpmnTaskTodoPageItemVO> getTodoTaskPage(@Validated @RequestBody BpmnTaskPageSearchDTO dto);

    /**
     * 已完成的审批列表
     */
    @Operation(summary = "已完成的审批列表")
    @GetMapping("/api/process/task/page/done")
    @Manageable
    @InvokeMode(SYNC)
    BpmPageResult<BpmnTaskDonePageItemVO> getDoneTaskPage(@Validated @RequestBody BpmnTaskPageSearchDTO dto);

    /**
     * 获取指定流程实例的审批过程信息
     * <p>
     * 同一层级结构
     */
    @Operation(summary = "获取指定流程实例的审批过程信息")
    @GetMapping("/api/process/task/list/flat")
    @Manageable
    @InvokeMode(SYNC)
    List<BpmnHistoricTaskInstanceVO> getTaskListFlatByProcessInstanceId(@NotBlank(message = "流程实例 ID " + "不能为空") @RequestParam String processInstanceId, @Nullable @RequestParam(required = false) String tenantId);

    /**
     * 获取指定流程实例的审批过程信息
     * <p>
     * 分组结构
     */
    @Operation(summary = "获取指定流程实例的审批过程信息")
    @GetMapping("/api/process/task/list/group")
    @Manageable
    @InvokeMode(SYNC)
    List<BpmnHistoricTaskInstanceGroupVO> getTaskListGroupByProcessInstanceId(@NotBlank(message = "流程实例 ID 不能为空") @RequestParam String processInstanceId, @Nullable @RequestParam(required = false) String tenantId);

    /**
     * 获取实例正在审核的人列表
     */
    @Operation(summary = "获取实例正在审核的人列表")
    @GetMapping("/api/process/task/active/list")
    @Manageable
    @InvokeMode(SYNC)
    List<BpmnTaskInstanceVO> getActiveTasksByProcessInstanceId(@NotBlank(message = "流程实例 ID 不能为空") @RequestParam String processInstanceId, @NotBlank(message = "租户不能为空") @RequestParam String tenantId);

    /**
     * 根据实例 ID 和自然人 ID 查询对应待处理的任务 ID
     *
     * @return
     */
    @Operation(summary = "根据实例 ID 和自然人 ID 查询对应待处理的任务 ID")
    @GetMapping("/api/process/task/find")
    @Manageable
    @InvokeMode(SYNC)
    String findTaskIdByInstanceIdAndPersonId(@RequestParam(required = false) @NotBlank(message = "流程实例 ID 不能为空") String processInstanceId, @RequestParam(required = false) @NotBlank(message = "自然人 ID 不能为空") String personId);

    /**
     * 根据实例 ID列表 和自然人 ID 查询对应待处理的任务 ID
     *
     * @return
     */
    @Operation(summary = "根据实例 ID列表 和自然人 ID 查询对应待处理的任务 ID")
    @GetMapping("/api/process/task/batch/find")
    @Manageable
    @InvokeMode(SYNC)
    Map<String, String> findTaskIdByInstanceIdsAndPersonId(@RequestParam(required = false) @NotEmpty(message = "流程实例 ID列表 不能为空") List<String> processInstanceIds, @RequestParam(required = false) @NotBlank(message = "自然人 ID 不能为空") String personId);

    /**
     * 获取活跃的流程定义分页
     */
    @GetMapping("/api/process/definition/page")
    @InvokeMode(SYNC)
    BpmPageResult<BpmnProcessDefinitionVO> getProcessDefinitionPage(@Validated @RequestBody BpmnProcessDefinitionPageDTO dto);

    /**
     * 通过模型 ID 更新流程定义
     *
     * @param dto
     * @return
     */
    @PutMapping("/api/process/definition/update")
    @InvokeMode(SYNC)
    Boolean updateProcessDefinition(@Validated @RequestBody BpmnProcessDefinitionUpdateDTO dto);

    /**
     * 获得指定定义编号对应的流程定义内容
     *
     * @param processDefinitionId 编号
     * @return 流程定义
     */
    @GetMapping("/api/process/definition/get")
    @InvokeMode(SYNC)
    BpmnProcessDefinitionVO getProcessDefinition(@NotBlank(message = "流程定义 ID 不能为空") @RequestParam String processDefinitionId);

    /**
     * 获得 deploymentId 对应的 ProcessDefinition
     *
     * @param deploymentId 部署编号
     * @return 流程定义
     */
    @GetMapping("/api/process/definition/getByDeploymentId")
    @InvokeMode(SYNC)
    BpmnProcessDefinitionVO getProcessDefinitionByDeploymentId(@NotBlank(message = "流程部署 ID 不能为空") @RequestParam String deploymentId);

    /**
     * 获得流程定义标识对应的激活的流程定义
     *
     * @param key 流程定义的标识
     * @return 流程定义
     */
    @GetMapping("/api/process/definition/active/getByKey")
    @InvokeMode(SYNC)
    BpmnProcessDefinitionVO getActiveProcessDefinitionByKey(@NotBlank(message = "模型定义KEY不能为空") @RequestParam String key, @RequestParam(required = false, defaultValue = NO_TENANT_ID) String tenantId);

    /**
     * 挂起/激活流程，
     * 激活：SuspensionState.ACTIVE.getStateCode()
     * 挂起：SuspensionState.SUSPENDED.getStateCode()
     * {@see SuspensionState}
     */
    @PutMapping("/api/process/definition/state/update")
    @InvokeMode(SYNC)
    Boolean getActiveProcessDefinitionByKey(@NotBlank(message = "流程定义ID不能为空") @RequestParam String processDefinitionId, @NotNull(message = "状态不能为空") @RequestParam Integer state);

    /**
     * 获取指定模型的定义 ID
     *
     * @return 流程定义ID
     */
    @GetMapping("/api/process/definition/active/getByCategory")
    @InvokeMode(SYNC)
    String getActiveProcessDefinitionId(@RequestParam(required = false) String tenantId, @NotBlank(message = "分类不能为空") @RequestParam(required = false) String category);

    /**
     * 获取指定模型激活的流程定义 JSON 模型
     *
     * @return 流程定义ID
     */
    @GetMapping("/api/process/definition/active/json/model")
    @InvokeMode(SYNC)
    BpmnModelUpdateDTO getActiveProcessDefinitionJsonModel(@NotBlank(message = "模型 ID 不能为空") @RequestParam(required = false) String modelId, @NotBlank(message = "分类不能为空") @RequestParam(required = false) String key, @RequestParam(required = false) String tenantId);

    /**
     * 删除流程部署及定义
     *
     * @param deploymentId 流程定义部署 ID
     * @param cascade      是否级联参数定义对应的流程实例及 job 等管理内容
     * @return
     */
    @GetMapping("/api/process/definition/delete")
    @InvokeMode(SYNC)
    Void delete(@NotBlank(message = "流程定义部署 ID 不能为空") String deploymentId, @RequestParam(required = false) Boolean cascade);

    /**
     * 强制使用‘同步’模式调用该方法，请在调用真实方法前调用该方法
     * <pre>
     *   workflowManageService.sync().getTenantIds();
     * </pre>
     */
    default WorkflowManageService sync() {
        ThreadUtil.set(SYNC);
        return this;
    }

    /**
     * 强制使用‘异步’模式调用该方法，请在调用真实方法前调用该方法
     * <pre>
     *   workflowManageService.async().getTenantIds();
     * </pre>
     */
    default WorkflowManageService async() {
        ThreadUtil.set(ASYNC);
        return this;
    }
}
