package cn.axzo.workflow.core.service;

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.BpmnProcessInstanceBatchQueryDTO;
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.HistoricProcessInstanceSearchDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.SuperBpmnProcessInstanceCancelDTO;
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.BpmPageResult;
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.HistoricProcessInstanceVO;
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 org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.form.api.FormInfo;

import javax.annotation.Nullable;
import javax.validation.Valid;
import java.util.List;

public interface BpmnProcessInstanceService {

    List<NodesByModelVO> nodesBeforeCreateProcessInstance(BeforeProcessInstanceCreateDTO dto);

    /**
     * 发起审核
     */
    String createProcessInstance(BpmnProcessInstanceCreateDTO processInstanceCreateDTO);

    FormInfo getStartFormModel(String processDefinitionId, String processInstanceId);

    /**
     * 取消流程实例
     *
     * @return true or false, true mean's cancelled
     */
    Boolean cancelProcessInstance(SuperBpmnProcessInstanceCancelDTO processInstanceCancelDTO);

    /**
     * 中止流程实例
     *
     * @param dto
     * @return
     */
    Boolean abortProcessInstance(BpmnProcessInstanceAbortDTO dto);

    /**
     * 批量中止流程实例
     *
     * @param dtos
     * @return
     */
    BatchOperationResultVO batchAbortProcessInstance(List<BpmnProcessInstanceAbortDTO> dtos);

    /**
     * 抄送流程实例
     *
     * @param dto
     * @return
     */
    Boolean carbonCopyProcessInstance(BpmnProcessInstanceCarbonCopyDTO dto);

    /**
     * 超管查询所有流程实例数据
     *
     * @param dto
     * @return
     */
    BpmPageResult<BpmnProcessInstanceAdminPageItemVO> getAdminProcessInstancePage(BpmnProcessInstanceAdminPageReqVO dto);

    /**
     * 获得流程实例的分页 / 我发起的审批列表
     *
     * @param pageReqVO 分页请求
     * @return 流程实例的分页
     */
    BpmPageResult<BpmnProcessInstancePageItemVO> getMyProcessInstancePage(@Valid BpmnProcessInstanceMyPageReqVO pageReqVO);

    /**
     * 获得流程实例
     *
     * @param businessKey 创建工作流实例时,业务传入的 businessKey
     * @param tenantId    租户 ID,非必传
     * @return 流程实例
     */
    HistoricProcessInstance getProcessInstanceByBusinessKey(String businessKey, @Nullable String tenantId,
                                                            @Nullable Boolean hasVariables);

    /**
     * 获得流程实例
     *
     * @param id          流程实例的编号
     * @param tenantId    租户Id
     * @param hasVariable 查询结果是否包含流程参数，
     * @return 流程实例, 租户Id不必传
     */
    HistoricProcessInstance getProcessInstance(String id, @Nullable String tenantId, @Nullable Boolean hasVariable);

    /**
     * 获得流程实例
     *
     * @param processDefinitionId 流程实例的编号
     * @param status              状态
     * @link SuspensionState.ACTIVE.getStateCode()
     */
    Boolean updateProcessStatus(String processDefinitionId, Integer status);

    /**
     * 获得历史的流程实例
     *
     * @param id 流程实例的编号
     * @return 历史的流程实例
     */
    HistoricProcessInstance getHistoricProcessInstance(String id, String tenantId);

    /**
     * 获得流程实例 VO 信息
     *
     * @return 流程实例
     */
    BpmnProcessInstanceVO getProcessInstanceVO(BpmnProcessInstanceQueryDTO dto);

    /**
     * 批量获得流程实例 VO 信息
     *
     * @param dto
     * @return
     */
    List<BpmnProcessInstanceVO> getBatchProcessInstanceVO(BpmnProcessInstanceBatchQueryDTO dto);

    ObjectNode getProcessInstanceGraphical(String processInstanceId, @Nullable String tenantId);

    BpmPageResult<HistoricProcessInstanceVO> historicProcessInstancePage(HistoricProcessInstanceSearchDTO dto);

    /**
     * 流程实例全节点推测
     *
     * @param processInstanceId
     * @param tenantId
     * @return
     */
    List<ProcessNodeDetailVO> getProcessInstanceNodeForecast(String processInstanceId, String tenantId);

    /**
     * 对指定流程的指定节点开始推送未来的结点，并结合变量计算正确的分支
     *
     * @param processInstanceId        实例编号
     * @param startNodeDefinitionKey   从该节点开始推断后续的节点
     * @param containSelf              是否包含起始节点
     * @param checkAliveThrowException 如果给的实例编号已到终态，不会执行推测，用该参数为 true 时，抛出实例完结的异常信息，如果为 false时，直接返回空集合
     * @return
     */
    List<ProcessNodeDetailVO> getProcessInstanceNodeForecastWithSpecifyTaskDefinitionKey(String processInstanceId, ProcessInstance instance, String startNodeDefinitionKey, Boolean containSelf, Boolean checkAliveThrowException);

    List<ProcessNodeDetailVO> getProcessInstanceNodeFilterForecast(String processInstanceId, String tenantId, List<String> nodeDefinitionKeys);

    List<String> getTenantIds();

    Boolean checkInstanceApprover(BpmnProcessInstanceCheckApproverDTO dto);

    /**
     * 获取指定流程实例的日志
     *
     * @param dto
     * @return
     */
    BpmnProcessInstanceLogVO getProcessInstanceLog(BpmnProcessInstanceLogQueryDTO dto);

    /**
     * 根据流程实例id,任务id，查询任务状态，按钮配置
     *
     * @param taskButtonsSearchDTO 请求参数
     * @return 任务按钮，状态信息
     */
    BpmnTaskButtonVo findTaskButtons(BpmnTaskButtonSearchDTO taskButtonsSearchDTO);

    /**
     * 获取指定流程实例对应的模型 ID
     *
     * @param processInstanceId
     * @return
     */
    String getModelIdByProcessInstanceId(String processInstanceId);

    String getModelIdByProcessDefinitionId(String processInstanceId, String processDefinitionId);

    /**
     * 覆盖指定流程表单的指定表单项
     *
     * @param dto
     */
    void overrideFormVariables(FormVariablesUpdateDTO dto);

    boolean hasPrintTemplate(String processInstanceId, String processDefinitionId);

    List<DocPendingVO> processInstanceSelectDocs(ProcessDocQueryDTO dto);
}
