package org.springblade.flow.engine.service.impl;

import static org.springblade.flow.base.util.BpmnModelUtils.getAttributeValueByTaskDefinitionKey;
import static org.springblade.flow.base.util.BpmnModelUtils.getBpmnModelMainProcess;
import static org.springblade.flow.engine.custom.constants.GlobalProcessVariableConstants.FORM_INFO_JSON;

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

import javax.annotation.Resource;

import org.flowable.bpmn.model.Process;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.variable.api.history.HistoricVariableInstance;
import org.springblade.flow.base.UserInfo;
import org.springblade.flow.base.util.ActivitiUtils;
import org.springblade.flow.base.util.FlowDataUtil;
import org.springblade.flow.base.util.FormCloumnUtil;
import org.springblade.flow.database.model.DbLinkEntity;
import org.springblade.flow.engine.assembly.GlobalExPropertyDTO;
import org.springblade.flow.engine.custom.constants.GlobalProcessVariableConstants;
import org.springblade.flow.engine.custom.variables.entity.FormDataInfo;
import org.springblade.flow.engine.entity.FlowEngineEntity;
import org.springblade.flow.engine.entity.FlowTaskEntity;
import org.springblade.flow.engine.model.flowtask.FlowTableModel;
import org.springblade.flow.engine.model.flowtask.FlowTaskInfoVO;
import org.springblade.flow.engine.service.FlowDynamicService;
import org.springblade.flow.engine.service.FlowEngineService;
import org.springblade.flow.engine.util.ModelUtil;
import org.springblade.flow.exception.WorkFlowException;
import org.springblade.flow.model.FormAllModel;
import org.springblade.flow.model.visiual.FormDataModel;
import org.springblade.flow.model.visiual.fields.FieldsModel;
import org.springblade.flow.util.JsonUtil;
import org.springblade.flow.util.JsonUtilEx;
import org.springblade.flow.util.RandomUtil;
import org.springblade.flow.util.StringUtil;
import org.springblade.flow.util.UserProvider;
import org.springblade.flow.visual.onlinedev.common.dynamic.DataSourceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;

/**
 * 在线开发工作流
 *
 * @author JNPF开发平台组
 * @version V3.1.0
 * @copyright 引迈信息技术有限公司
 * @date 2021/3/15 9:19
 */
@Service
public class FlowDynamicServiceImpl implements FlowDynamicService {

	@Autowired
	private FlowEngineService flowEngineService;
	@Autowired
	private UserProvider userProvider;
	@Autowired
	private FlowDataUtil flowDataUtil;
	@Autowired
	private DataSourceService dblinkService;
	@Resource
	private HistoryService historyService;
	@Resource
	private ActivitiUtils activitiUtils;
	@Resource
	private RuntimeService runtimeService;

	@Override
	public FlowTaskInfoVO info(String processInstanceId) throws WorkFlowException {
//        FlowEngineEntity flowentity = flowEngineService.getInfo(entity.getFlowId());

		List<HistoricVariableInstance> variableList = historyService.createHistoricVariableInstanceQuery()
				.processInstanceId(processInstanceId).list();
		FlowEngineEntity flowentity = null;
		String formInfoJson = "";
		for (HistoricVariableInstance historicVariableInstance : variableList) {

			if (GlobalProcessVariableConstants.FLOW_ENGINE_ID.equals(historicVariableInstance.getVariableName())) {
				flowentity = flowEngineService.getInfo(historicVariableInstance.getValue().toString());
			}
			if (FORM_INFO_JSON.equals(historicVariableInstance.getVariableName())) {
//                    formInfoJson=historicVariableInstance.getValue().toString();
				FormDataInfo formDataInfo = (FormDataInfo) historicVariableInstance.getValue();
				formInfoJson = formDataInfo.getFormDataJson();
			}
		}

		List<FlowTableModel> tableModelList = JsonUtil.getJsonToList(flowentity.getTables(), FlowTableModel.class);
//        FlowTaskInfoVO vo = JsonUtil.getJsonToBean(entity, FlowTaskInfoVO.class);

		FlowTaskInfoVO vo = new FlowTaskInfoVO();
		vo.setId(processInstanceId);
		vo.setFlowId(flowentity.getId());
		HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
				.processInstanceId(processInstanceId).singleResult();
		String processDefinitionId = historicProcessInstance.getProcessDefinitionId();

		Process process = getBpmnModelMainProcess(processDefinitionId);
		String property = getAttributeValueByTaskDefinitionKey(process, "", "global");
		GlobalExPropertyDTO activityExPropertyDTO = JSONObject.parseObject(property,
				new TypeReference<GlobalExPropertyDTO>() {
				});
		// formTempJson
		FormDataModel formData = JsonUtil.getJsonToBean(activityExPropertyDTO.getFormData(), FormDataModel.class);
		List<FieldsModel> list = JsonUtil.getJsonToList(formData.getFields(), FieldsModel.class);
		DbLinkEntity link = null;
		if (StringUtil.isNotEmpty(flowentity.getDbLinkId())) {
			link = dblinkService.getInfo(flowentity.getDbLinkId());
		}
		FlowTaskEntity entity = new FlowTaskEntity();
		entity.setId(historicProcessInstance.getBusinessKey());
		entity.setFlowFormContentJson(formInfoJson);
		Map<String, Object> result = flowDataUtil.info(list, entity, tableModelList, false, link);
		vo.setData(JsonUtilEx.getObjectToString(result));
		return vo;
	}

	@Override
	public void save(String id, String flowId, String data) throws WorkFlowException {
		FlowEngineEntity entity = flowEngineService.getInfo(flowId);
		UserInfo info = userProvider.get();
		String billNo = "单据规则不存在";
		String title = info.getUserName() + "的" + entity.getFullName();
		String formId = RandomUtil.uuId();
		// formTempJson
		FormDataModel formData = JsonUtil.getJsonToBean(entity.getFormData(), FormDataModel.class);
		List<FieldsModel> list = JsonUtil.getJsonToList(formData.getFields(), FieldsModel.class);
		List<FormAllModel> formAllModel = new ArrayList<>();
		FormCloumnUtil.recursionForm(list, formAllModel);
		// 主表的单据数据
		Map<String, String> billData = new HashMap<>(16);
		boolean type = id != null;
		if (type) {
			formId = id;
		}
		// tableJson
		List<FlowTableModel> tableModelList = JsonUtil.getJsonToList(entity.getTables(), FlowTableModel.class);
		// 表单值
		Map<String, Object> dataMap = JsonUtil.stringToMap(data);
		Map<String, Object> result = new HashMap<>(16);
		DbLinkEntity link = null;
		if (StringUtil.isNotEmpty(entity.getDbLinkId())) {
			link = dblinkService.getInfo(entity.getDbLinkId());
		}
		if (type) {
			result = flowDataUtil.update(dataMap, list, tableModelList, formId, link);
		} else {
			result = flowDataUtil.create(dataMap, list, tableModelList, formId, billData, link);
		}
		// 流程信息
		ModelUtil.save(id, flowId, formId, title, 1, billNo, result);
	}

	@Override
	public void submit(String id, String flowId, String data, String freeUserId) throws WorkFlowException {
		FlowEngineEntity entity = flowEngineService.getInfo(flowId);
		UserInfo info = userProvider.get();
		String billNo = "单据规则不存在";
		String title = info.getUserName() + "的" + entity.getFullName();
		String formId = RandomUtil.uuId();
		// formTempJson
		FormDataModel formData = JsonUtil.getJsonToBean(entity.getFormData(), FormDataModel.class);
		List<FieldsModel> list = JsonUtil.getJsonToList(formData.getFields(), FieldsModel.class);
		List<FormAllModel> formAllModel = new ArrayList<>();
		FormCloumnUtil.recursionForm(list, formAllModel);
		// 主表的单据数据
		Map<String, String> billData = new HashMap<>(16);
		boolean type = id != null;
		if (type) {
			formId = id;
		}
		// tableJson
		List<FlowTableModel> tableModelList = JsonUtil.getJsonToList(entity.getTables(), FlowTableModel.class);
		// 表单值
		Map<String, Object> dataMap = JsonUtil.stringToMap(data);
		Map<String, Object> result = new HashMap<>(16);
		DbLinkEntity link = null;
		if (StringUtil.isNotEmpty(entity.getDbLinkId())) {
			link = dblinkService.getInfo(entity.getDbLinkId());
		}
		if (type) {
			result = flowDataUtil.update(dataMap, list, tableModelList, formId, link);
		} else {
			result = flowDataUtil.create(dataMap, list, tableModelList, formId, billData, link);
		}
		// 流程信息
		ModelUtil.submit(id, flowId, formId, title, 1, billNo, result, freeUserId);
	}

	@Override
	public Map<String, Object> getData(String flowId, String id) throws WorkFlowException {
		ProcessInstance processInstance = activitiUtils.getProcessInstanceByIdOrBusinessKey(id);
//        FlowTaskEntity entity = flowTaskService.getInfo(id);
		FlowEngineEntity flowentity = flowEngineService.getInfo(flowId);
		List<FlowTableModel> tableModelList = JsonUtil.getJsonToList(flowentity.getTables(), FlowTableModel.class);

		String processDefinitionId = processInstance.getProcessDefinitionId();

		Process process = getBpmnModelMainProcess(processDefinitionId);
		String property = getAttributeValueByTaskDefinitionKey(process, "", "global");
		GlobalExPropertyDTO activityExPropertyDTO = JSONObject.parseObject(property,
				new TypeReference<GlobalExPropertyDTO>() {
				});

		// formTempJson
		FormDataModel formData = JsonUtil.getJsonToBean(activityExPropertyDTO.getFormData(), FormDataModel.class);
		List<FieldsModel> list = JsonUtil.getJsonToList(formData.getFields(), FieldsModel.class);
		DbLinkEntity link = null;
		if (StringUtil.isNotEmpty(flowentity.getDbLinkId())) {
			link = dblinkService.getInfo(flowentity.getDbLinkId());
		}

		FlowTaskEntity flowTaskEntity = new FlowTaskEntity();
		flowTaskEntity.setId(processInstance.getBusinessKey());
		FormDataInfo formDataInfo = runtimeService.getVariable(processInstance.getId(), FORM_INFO_JSON,
				FormDataInfo.class);
		flowTaskEntity.setFlowFormContentJson(formDataInfo.getFormDataJson());
		Map<String, Object> resultData = flowDataUtil.info(list, flowTaskEntity, tableModelList, true, link);
		return resultData;
	}

}
