package com.testor.workflow.form.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.xiaoymin.knife4j.core.util.StrUtil;
import com.testor.workflow.form.model.ZFormDTO;
import com.testor.workflow.form.model.ZModelFormDTO;
import com.testor.workflow.form.service.ZFormService;
import lombok.extern.slf4j.Slf4j;
import org.flowable.ui.common.service.exception.ConflictingRequestException;
import org.flowable.ui.modeler.domain.Model;
import org.flowable.ui.modeler.model.ModelKeyRepresentation;
import org.flowable.ui.modeler.model.ModelRepresentation;
import org.flowable.ui.modeler.serviceapi.ModelService;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ZFormServiceImpl implements ZFormService {

    @Resource
    private ModelService modelService;

    @Override
    public ModelRepresentation createForm(ZFormDTO zformDto){
        ModelRepresentation model = new ModelRepresentation();
        model.setKey(zformDto.getKey().replaceAll(" ", ""));
        checkForDuplicateKey(model);

        model.setName(zformDto.getName());

        if(!StrUtil.isBlank(zformDto.getDescription())) {
            model.setDescription(zformDto.getDescription());
        }
        model.setModelType(zformDto.getModelType());

        Map modelJsonMap = new HashMap();
        modelJsonMap.put("name", zformDto.getName());
        modelJsonMap.put("key", zformDto.getKey());
        modelJsonMap.put("fields", zformDto.getFormItemList());
        Model newModel = modelService.createModel(model, JSON.toJSONString(modelJsonMap), zformDto.getUser());
        model.setId(newModel.getId());
        return model;
    }

    /**
     * form绑定流程节点
     * @param zmodelFormDto
     */
    public boolean bindModelForm(@RequestBody ZModelFormDTO zmodelFormDto) {
        Model model = modelService.getModel(zmodelFormDto.getModelId());
        String modelJson = model.getModelEditorJson();
        if(StrUtil.isBlank(modelJson)){
            return false;
        }

        Map modelJsonObj = JSON.parseObject(modelJson, Map.class);
        if(modelJsonObj.get("childShapes") == null) {
            return false;
        }

        String elementNodeId = zmodelFormDto.getElementNodeId();
        List<Map> jsonElementList = JSON.parseArray(modelJsonObj.get("childShapes").toString(), Map.class);
        //获取匹配的节点
        Map elementNode = jsonElementList.stream().filter(element -> {
            String resourceId = element.get("resourceId").toString();
            if(!StrUtil.isBlank(resourceId) && resourceId.equals(elementNodeId)) {
                return true;
            }
            return false;
        }).findAny().get();

        if(elementNode == null) {
            return false;
        }

        Map elPros = JSON.parseObject(elementNode.get("properties").toString(), Map.class);

        Map formRef = new HashMap();
        formRef.put("id", zmodelFormDto.getId());
        formRef.put("name", zmodelFormDto.getName());
        formRef.put("key", zmodelFormDto.getKey());

        elPros.put("formreference", JSON.toJSON(formRef));
        elementNode.put("properties", elPros);
        List<Map> replacedEleList = jsonElementList.stream().map(element -> {
            String resourceId = element.get("resourceId").toString();
            if(!StrUtil.isBlank(resourceId) && resourceId.equals(elementNodeId)) {
                return elementNode;
            }
            return element;
        }).collect(Collectors.toList());
        modelJsonObj.put("childShapes", replacedEleList);
        model.setModelEditorJson(JSON.toJSONString(modelJsonObj));
        modelService.saveModel(model);
        return true;
    }

    protected void checkForDuplicateKey(ModelRepresentation modelRepresentation) {
        ModelKeyRepresentation modelKeyInfo = modelService.validateModelKey(null, modelRepresentation.getModelType(), modelRepresentation.getKey());
        if (modelKeyInfo.isKeyAlreadyExists()) {
            throw new ConflictingRequestException("Provided model key already exists: " + modelRepresentation.getKey());
        }
    }
}
