package com.bbd.bpm.controller.deployment;

import com.bbd.bpm.base.PageBean;
import com.bbd.bpm.domain.ActReModelEntity;
import com.bbd.bpm.dto.SysCode;
import com.bbd.bpm.dto.response.BpmResponse;
import com.bbd.bpm.dto.request.StartModelRequest;
import com.bbd.bpm.result.Result;
import com.bbd.bpm.service.ActReModelService;
import com.bbd.bpm.util.validate.ValidateUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.IdentityService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.DeploymentBuilder;
import org.activiti.engine.repository.Model;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

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

/**
 * Created by houkang on 2019/2/22.
 */
@RestController
@RequestMapping("/api/bpm/model")
@Api(tags = {"流程管理"})
public class DeploymentController {
    private static final Logger Log = LoggerFactory.getLogger(DeploymentController.class);

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private IdentityService identityService;

    @Autowired
    private ActReModelService actReModelService;


    @ApiOperation(value = "查询流程列表")
    @RequestMapping(value = "/modelList")
    public BpmResponse modelList(PageBean pageBean) {
        BpmResponse resp = new BpmResponse();
        try{
            if(pageBean.getPageNum()==0){
                pageBean.setPageNum(1);
            }
            if (pageBean.getPageSize()==0) {
                pageBean.setPageSize(10);
            }
            //获取流程列表
            Result result= actReModelService.getList(pageBean);
            resp.setData(result);
            resp.setCode(SysCode.SUCCESS_CODE);
            resp.setSuccess(true);
            resp.setMessage("获取成功");
        }catch (Exception e){
            Log.error("获取失败",e);
            resp.setSuccess(false);
            resp.setMessage("查询失败"+e.getMessage());
            resp.setCode(SysCode.SYS_ERROR);
        }
        return resp;
    }


    @ApiOperation(value = "删除流程")
    @GetMapping("/deleteModel")
    public BpmResponse deleteModel(String modelId) {
        BpmResponse resp = new BpmResponse();
        try{
            //校验参数
            if(StringUtils.isBlank(modelId) ){
                resp.setMessage("流程id"+SysCode.NOT_ALLOW_NULL);
                resp.setCode(SysCode.VALIDATE_ERROR);
                resp.setSuccess(false);
                return resp;
            }
            Model modelData = repositoryService.getModel(modelId);
            if(modelData==null||modelData.getId()==null){
                resp.setMessage("流程不存在");
                resp.setCode(SysCode.VALIDATE_ERROR);
                resp.setSuccess(false);
                return resp;
            }
            //判断是否有未完成的流程
            if(modelData.getDeploymentId()!=null){
                ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(modelData.getDeploymentId()).singleResult();
                List<ProcessInstance> piList = runtimeService.createProcessInstanceQuery().processDefinitionKey(processDefinition.getKey()).list();
                if(piList!=null && !piList.isEmpty()){
                    for(ProcessInstance pi : piList){
                        if(!pi.isEnded()){
                            resp.setMessage("尚有流程实例正在执行");
                            resp.setCode(SysCode.VALIDATE_ERROR);
                            resp.setSuccess(false);
                            return resp;
                        }
                    }
                }
            }

            repositoryService.deleteModel(modelId);
            resp.setSuccess(true);
            resp.setMessage("删除成功");
            resp.setCode(SysCode.SUCCESS_CODE);
        }catch (Exception e){
            Log.error("删除失败",e);
            resp.setSuccess(false);
            resp.setMessage("删除失败"+e.getMessage());
            resp.setCode(SysCode.SYS_ERROR);
        }
        return resp;
    }



    @ApiOperation(value = "部署流程")
    @GetMapping("/deploymentModel")
    public BpmResponse deploymentModel(final String modelId) {
        BpmResponse resp = new BpmResponse();
        resp.setSuccess(true);
        try {
            Model modelData = repositoryService.getModel(modelId);
            ObjectNode modelNode = (ObjectNode) new ObjectMapper().readTree(repositoryService.getModelEditorSource(modelData.getId()));
            byte[] bpmnBytes = null;
            BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode);
            bpmnBytes = new BpmnXMLConverter().convertToXML(model);
            String processName = modelData.getName() + ".bpmn20.xml";
            DeploymentBuilder db = repositoryService.createDeployment().name(modelData.getName());
            Deployment deployment = db.addString(processName, new String(bpmnBytes,"utf-8")).deploy();
            //需要在 model表里保存 deploymentid
            modelData.setDeploymentId(deployment.getId());
            repositoryService.saveModel(modelData);
            resp.setData(deployment.getId());
        } catch (Exception e) {
            Log.error(modelId+"部署失败",e);
            resp.setSuccess(false);
            resp.setMessage("部署失败"+e.getMessage());
            resp.setCode(SysCode.SYS_ERROR);
        }

        return resp;
    }

    @ApiOperation(value = "删除部署")
    @GetMapping("/deleteDeployment")
    public BpmResponse deleteDeployment(String deploymentId) {
        BpmResponse resp = new BpmResponse();
       // processEngine.getRepositoryService().deleteDeployment(deploymentId, true);
       //todo
        try{
            repositoryService.deleteDeployment(deploymentId, true);
            System.out.println("删除流程成功，当前流程部署ID：" + deploymentId);
            resp.setSuccess(true);
            resp.setMessage("删除成功");
        }catch (Exception e){
            Log.error("删除失败",e);
            resp.setSuccess(false);
            resp.setMessage("删除失败"+e.getMessage());
            resp.setCode(SysCode.SYS_ERROR);
        }
        return resp;
    }

    @ApiOperation(value = "发起流程实例")
    @PostMapping("/startModel")
    public BpmResponse startModel(@RequestBody StartModelRequest req) {
        BpmResponse resp = new BpmResponse();
        try {
            //数据校验
            String error = ValidateUtil.check_startModel(req);
            if(error!=null){
                Log.error("发起流程实例，数据校验失败"+error);
                resp.setCode(SysCode.VALIDATE_ERROR);
                resp.setMessage(error);
                resp.setSuccess(false);
                return resp;
            }
            //获取流程定义
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(req.getDeploymentId()).singleResult();
            //启动流程定义，返回流程实例
            Map<String, Object> variables = req.getVariables();
            // 用来设置启动流程的人员ID，引擎会自动把用户ID保存到activiti:initiator中
            identityService.setAuthenticatedUserId(req.getUserId());
            ProcessInstance pi = runtimeService.startProcessInstanceByKey(processDefinition.getKey(), req.getBussinessKey(),variables);
            String processId = pi.getId();
            Log.info("流程发起成功，当前流程实例ID：" + processId);
            resp.setData(processId);
            resp.setCode(SysCode.SUCCESS_CODE);
        } catch (Exception e) {
            Log.error(req.getDeploymentId()+"发起流程实例失败",e);
            resp.setSuccess(false);
            resp.setMessage("发起流程实例失败"+e.getMessage());
            resp.setCode(SysCode.SYS_ERROR);
        }
        return resp;


    }
}
