package cn.axzo.workflow.client.feign.bpmn;

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.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.RestPrintTemplateConfigDTO;
import cn.axzo.workflow.common.model.response.BpmPageResult;
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.azxo.framework.common.model.CommonResponse;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.List;

import static cn.axzo.workflow.common.enums.RpcInvokeModeEnum.SYNC;

/**
 * 流程模型 API
 *
 * @author wangli
 * @since 2023/9/21 15:47
 */
//@FeignClient(name = "workflow-engine", url = "${axzo.service.workflow-engine:http://workflow-engine:8080}", configuration = CommonFeignConfiguration.class)
@WorkflowEngineFeignClient
@Manageable
public interface ProcessModelApi {

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

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

    /**
     * 通过模型 ID 获取模型
     */
    @Operation(summary = "通过模型ID查询指定流程模型")
    @GetMapping("/api/process/model/get")
    @InvokeMode(SYNC)
    CommonResponse<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)
    CommonResponse<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)
    CommonResponse<BpmnModelExtVO> getModelExt(@NotBlank(message = "模型 ID 不能为空") @RequestParam(required = false) String modelId);

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


    /**
     * 通过模型 ID 部署模型
     *
     * @return 部署完成的流程定义Id
     */
    @Operation(summary = "通过模型 ID 部署流程模型")
    @PostMapping("/api/process/model/deploy")
    @InvokeMode(SYNC)
    CommonResponse<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)
    CommonResponse<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)
    CommonResponse<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)
    CommonResponse<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)
    CommonResponse<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)
    CommonResponse<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)
    CommonResponse<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)
    CommonResponse<List<String>> getModelCategoryList();

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

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

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

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

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

    /**
     * 获取指定模板的原始文档列表
     *
     * @param dto
     * @return
     */
    @Operation(summary = "根据业务 ID 获取模型文档列表，自动适配公共模板和代运营")
    @PostMapping(value = "/api/process/model/doc/list")
    @InvokeMode(SYNC)
    CommonResponse<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)
    CommonResponse<String> getHiPrintContent(@RequestParam String fileRelationId);

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

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

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

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

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

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

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

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

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