package com.ibiz.activiti.service.external;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ibiz.activiti.ActivitiWFApplication.WebClientProperties;
import com.ibiz.activiti.feign.FeignRequestInterceptor;
import com.ibiz.activiti.feign.UniWFFeignClient;
import com.ibiz.activiti.util.WFStepUtil;
import feign.Client;
import feign.Contract;
import feign.Feign;
import feign.codec.Decoder;
import feign.codec.Encoder;
import org.activiti.api.process.runtime.ProcessRuntime;
import org.activiti.api.task.runtime.TaskRuntime;
import org.activiti.bpmn.model.FormProperty;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.delegate.event.ActivitiEvent;
import org.activiti.engine.delegate.event.impl.ActivitiActivityEventImpl;
import org.activiti.engine.delegate.event.impl.ActivitiEventImpl;
import org.activiti.engine.delegate.event.impl.ActivitiProcessStartedEventImpl;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.impl.persistence.entity.ExecutionEntityImpl;
import org.activiti.engine.impl.persistence.entity.IdentityLinkEntity;
import org.activiti.engine.impl.persistence.entity.TaskEntityImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.List;

/**
 * 调用统一系统服务
 */
@Service
public class UniWFService  {

	UniWFFeignClient client;
	@Autowired
	WFStepUtil wfStepUtil;
	@Autowired
	ProcessRuntime processRuntime;
	@Autowired
	TaskRuntime taskRuntime;
	@Autowired
	HistoryService historyService;
	@Autowired
	TaskService taskService;
	@Autowired
	RepositoryService repositoryService;
	@Autowired
	RuntimeService runtimeService;

	@Autowired
	public UniWFService(Decoder decoder, Encoder encoder, Client client, Contract contract, FeignRequestInterceptor feignRequestInterceptor,
						WebClientProperties webClientProperties) {
		if (webClientProperties.getServiceId()!=null) {
			Feign.Builder nameBuilder = Feign.builder()
					.client(client)
					.encoder(encoder)
					.decoder(decoder)
					.contract(contract)
					.requestInterceptor(feignRequestInterceptor)
					;
			this.client = nameBuilder.target(UniWFFeignClient.class,"http://" + webClientProperties.getServiceId() + "/") ;
		} else if (webClientProperties.getServiceUrl()!=null) {
			if (client instanceof LoadBalancerFeignClient) {
				client = ((LoadBalancerFeignClient) client).getDelegate();
			}
			Feign.Builder nameBuilder = Feign.builder()
					.client(client)
					.encoder(encoder)
					.decoder(decoder)
					.contract(contract)
					.requestInterceptor(feignRequestInterceptor)
					;
			this.client = nameBuilder.target(UniWFFeignClient.class, "http://" + webClientProperties.getServiceUrl() + "/") ;
		}
	}


	/**
	 * 计算当前步骤操作者
	 * @param processInstanceId 流程实例标识
	 * @param curStepId 流程步骤标识
	 * @return
	 */
	public List<String> calculateCurrentWFStepActor(String processInstanceId,String curStepId) {

		List <String> wfStepUsers=new ArrayList<>();

		JSONObject json = new JSONObject() ;
		json.put("opperson", Authentication.getAuthenticatedUserId());
		json.put("instanceid", processInstanceId);
		json.put("curstep",curStepId.replaceFirst("ACTIVITI",""));

		JSONObject rspData = client.getWFUsers(json);

		if(!ObjectUtils.isEmpty(rspData)){
			JSONArray wfUsers=rspData.getJSONArray("users");
			if(wfUsers.size()>0){
				for(int a=0;a<wfUsers.size();a++){
					JSONObject userObj=wfUsers.getJSONObject(a);
					String wfUserId=userObj.getString("userid");
					if(!StringUtils.isEmpty(wfUserId)){
						wfStepUsers.add(wfUserId);
					}
				}
			}
		}

		return wfStepUsers;
	}

	/**
	 * 流程启动回调
	 * @param event
	 * @param executionEntity
	 * @return
	 */
	public JSONObject callbackWFProcessStarted(ActivitiEvent event, ExecutionEntityImpl executionEntity) {

		ActivitiProcessStartedEventImpl startEvent = (ActivitiProcessStartedEventImpl) event ;
		JSONObject reqData = new JSONObject() ;
		reqData.put("opperson",Authentication.getAuthenticatedUserId());
		reqData.put("wfinstanceid", startEvent.getVariables().get("srfwfinstanceid"));
		reqData.put("instanceid", startEvent.getProcessInstanceId());

		return client.wfProcessStarted(reqData);
	}

	/**
	 *  流程正常结束回调
	 * @param event
	 * @param executionEntity
	 * @return
	 */
	public JSONObject callbackWFProcessCompleted(ActivitiEvent event, ExecutionEntityImpl executionEntity) {

		JSONObject reqData = new JSONObject() ;
		reqData.put("opperson",Authentication.getAuthenticatedUserId());
		reqData.put("instanceid", event.getProcessInstanceId());

		return client.wfProcessCompleted(reqData);
	}

	/**
	 * 流程取消回调
	 * @param event
	 * @param executionEntity
	 * @return
	 */
	public JSONObject callbackWFProcessCancelled(ActivitiEvent event, ExecutionEntityImpl executionEntity) {

		JSONObject reqData = new JSONObject() ;
		reqData.put("opperson",Authentication.getAuthenticatedUserId());
		reqData.put("instanceid", event.getProcessInstanceId());

		return client.wfProcessCancelled(reqData);
	}

	/**
	 * 步骤开始回调
	 * @param activitiEvent
	 * @param curStep
	 * @return
	 */
	public JSONObject callbackWFActivityStarted(ActivitiEvent activitiEvent ,UserTask curStep) {

		JSONObject reqData = new JSONObject() ;
		reqData.put("opperson",Authentication.getAuthenticatedUserId());
		reqData.put("instanceid", activitiEvent.getProcessInstanceId());
		reqData.put("curstep",curStep.getId().replaceFirst("ACTIVITI",""));
		HistoricActivityInstance historicActivityInstance=wfStepUtil.getPreStep(activitiEvent.getProcessInstanceId());
		if(!ObjectUtils.isEmpty(historicActivityInstance)){
			reqData.put("prestep",historicActivityInstance.getActivityId());
		}
		return client.wfActivityStarted(reqData);
	}

	/**
	 * 步骤完成回调
	 * @param activitiEvent
	 * @param curStep
	 * @return
	 */
	public JSONObject callbackWFActivityCompleted(ActivitiEvent activitiEvent ,UserTask curStep) {
		JSONObject reqData = new JSONObject();
		reqData.put("opperson", Authentication.getAuthenticatedUserId());
		reqData.put("instanceid", activitiEvent.getProcessInstanceId());
		reqData.put("curstep", curStep.getId().replaceFirst("ACTIVITI", ""));
		HistoricActivityInstance historicActivityInstance = wfStepUtil.getPreStep(activitiEvent.getProcessInstanceId());
		if (!ObjectUtils.isEmpty(historicActivityInstance)) {
			reqData.put("prestep", historicActivityInstance.getActivityId());
		}
		return client.wfActivityCompleted(reqData);
	}

	/**
	 * 任务建立回调
	 * @param event
	 * @param curTask
	 * @return
	 */
	public JSONObject callbackWFTaskCreated(ActivitiEvent event , TaskEntityImpl curTask){

		JSONObject reqData = new JSONObject() ;
		reqData.put("opperson",Authentication.getAuthenticatedUserId());
		reqData.put("instanceid", event.getProcessInstanceId());
		reqData.put("taskid", curTask.getId()) ;
		reqData.put("taskname", curTask.getName());
		reqData.put("viewurl", curTask.getVariable("srfviewurl"));
		reqData.put("curstep",curTask.getTaskDefinitionKey().replaceFirst("ACTIVITI",""));

		//查询候选者
		JSONArray users = new JSONArray() ;
		for(IdentityLinkEntity identityLinkEntity : curTask.getIdentityLinks()) {
			JSONObject user = new JSONObject() ;
			user.put("id" ,identityLinkEntity.getId()) ;
			user.put("type" ,identityLinkEntity.getType()) ;
			user.put("userid" ,identityLinkEntity.getUserId()) ;
			users.add(user) ;
		}
		reqData.put("users",users) ;

		return client.wfTaskCreated(reqData) ;
	}

	/**
	 * 任务分配回调
	 * @param event
	 * @param curTask
	 * @return
	 */
	public JSONObject callbackWFTaskAssigned(ActivitiEvent event , TaskEntityImpl curTask) {

		JSONObject reqData = new JSONObject() ;
		return client.wfTaskAssigned(reqData);
	}

	/**
	 * 任务完成回调
	 * @param event
	 * @param curTask
	 * @return
	 */
	public JSONObject callbackWFTaskCompleted(ActivitiEvent event , TaskEntityImpl curTask) {

        Object srfWFMemo=curTask.getVariable("srfwfmemo");

		JSONObject reqData = new JSONObject();
		reqData.put("opperson",Authentication.getAuthenticatedUserId());
		reqData.put("instanceid", event.getProcessInstanceId());
		reqData.put("taskid", curTask.getId());
        reqData.put("opaction", curTask.getVariable("srfconnection"));
        if(ObjectUtils.isEmpty(srfWFMemo)){
            reqData.put("opactioninfo", "");
        }else{
            reqData.put("opactioninfo", srfWFMemo);
        }
		return client.wfTaskCompleted(reqData);
	}

	/**
	 * 步骤角色转换
	 * @param WFStepRoles
	 * @return
	 */
	private JSONArray form2List(List<FormProperty> WFStepRoles){

		JSONArray WFStepRolesArr=new JSONArray();

		for(FormProperty wfStepRole: WFStepRoles){
			JSONObject wfStepRoleObj=new JSONObject();
			wfStepRoleObj.put("wfstepactor",wfStepRole.getId());
			wfStepRoleObj.put("type",wfStepRole.getType());
			WFStepRolesArr.add(wfStepRoleObj);
		}
		return WFStepRolesArr;
	}
}