package com.bcxin.api.controllers;

import cn.myapps.common.auth.IUser;
import cn.myapps.common.controller.ErrorMessage;
import cn.myapps.common.controller.Resource;
import cn.myapps.common.data.ParamsTable;
import cn.myapps.common.util.StringUtil;
import cn.myapps.common.util.cache.MemoryCacheUtil;
import cn.myapps.constans.Web;
import cn.myapps.designtime.common.service.DesignTimeServiceManager;
import cn.myapps.runtime.common.service.RunTimeServiceManager;
import cn.myapps.runtime.dynaform.document.ejb.Document;
import cn.myapps.runtime.dynaform.document.ejb.DocumentProcess;
import cn.myapps.runtime.dynaform.document.ejb.Item;
import cn.myapps.runtime.dynaform.form.ejb.Form;
import cn.myapps.runtime.dynaform.form.ejb.ValidateMessage;
import cn.myapps.runtime.workflow.storage.runtime.ejb.FlowRuntimeService;
import cn.myapps.runtime.workflow.storage.runtime.ejb.FlowRuntimeServiceImpl;
import cn.myapps.runtime.workflow.storage.runtime.ejb.FlowStateRT;
import cn.myapps.util.ParamsTableUtil;
import com.bcxin.dtos.ExecuteActionResultDto;
import com.bcxin.enums.ActionStep;
import com.bcxin.runtime.apis.controllers.ControllerAbstract;
import com.bcxin.services.DocumentService;
import com.bcxin.services.commands.CreatedDocumentCommand;
import com.bcxin.services.commands.results.CreatedDocumentCommandResult;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.DocumentContext;
import com.jayway.jsonpath.Option;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

import static com.jayway.jsonpath.JsonPath.parse;

@RestController("v2_document_controller")
@RequestMapping("/api/runtime-ex/apps/{appId}")
public class DocumentController extends ControllerAbstract {

    private final DocumentService documentService;
    public DocumentController(DocumentService documentService) {
        this.documentService = documentService;
    }

    @PostMapping("/activities/{actId}/documents")
    public ResponseEntity<Resource> post(
            @PathVariable String appId, @PathVariable String actId,
            @RequestBody String content,
            @RequestParam ActionStep step,
            HttpServletRequest request) throws Exception {
        ParamsTable params = getParams(request);
        params = ParamsTableUtil.parseAndMergeActionB_A(params, actId, content, true);
        //Document doc = this.prepareDocument(content, appId, "$.document", params);
        IUser user = getWebUser();

        CreatedDocumentCommand command = CreatedDocumentCommand.create(appId, actId, step, params, content, user);
        CreatedDocumentCommandResult commandResult = this.documentService.dispatch(command);

        return ResponseEntity.ok((Resource) commandResult.getResult());
    }


    private ParamsTable getParams(HttpServletRequest request) {
        ParamsTable pm = ParamsTable.convertHTTP(request);
        String domainId = getCurrentDomainId(request);
        if (domainId != null) {
            pm.setParameter("domainid", domainId);
        }

        // put the page line count id to parameters table.
        if (pm.getParameter("_pagelines") == null)
            pm.setParameter("_pagelines", Web.DEFAULT_LINES_PER_PAGE);

        String parentId = pm.getParameterAsString("parentId");
        if (!StringUtil.isBlank(parentId)) {
            pm.setParameter("relateid", parentId);
            pm.setParameter("parentid", parentId);
        }
        String parentid = pm.getParameterAsString("parentid");
        if (!StringUtil.isBlank(parentid)) {
            pm.setParameter("relateid", parentid);
            pm.setParameter("parentId", parentid);
        }

        String isRelate = pm.getParameterAsString("isRelate");
        if (StringUtil.isBlank(isRelate) || !"true".equals(isRelate)) {
            pm.removeParameter("parentId");
            pm.removeParameter("parentid");
        }

        return pm;
    }

    private Document prepareDocument(String jsonContent, String applicationId, String baseJsonPath, ParamsTable params)
            throws Exception {
        Configuration configuration = Configuration.defaultConfiguration();
        configuration = configuration.addOptions(Option.DEFAULT_PATH_LEAF_TO_NULL);
        DocumentContext parse = parse(jsonContent, configuration);
        String formid = parse.read(baseJsonPath + ".formId");
        String viewid = parse.read(baseJsonPath + ".viewId");
        String stateid = parse.read(baseJsonPath + ".stateId");
        String parentid = parse.read(baseJsonPath + ".parentId");
        String sign = parse.read(baseJsonPath + ".sign");
        String docId = params.getDocId();
        if(StringUtil.isBlank(docId)) {
            docId = parse.read(baseJsonPath + ".id");
        }

        String isRelate = parse.read(baseJsonPath + ".isRelate");
        List subDocuments = parse.read(baseJsonPath + ".subDocuments");
        Map<String, Object> items = parse.read(baseJsonPath + ".items");
        Object delete = parse.read(baseJsonPath + ".delete");
        Object edit = parse.read(baseJsonPath + ".edit");
        Object isFromRefresh = params.getParameter("isFromRefresh");
        Object exparams = parse.read(baseJsonPath + ".exparams");

        if (exparams != null) {
            Map<String, Object> exparamsMap = (Map<String, Object>) exparams;
            for (Map.Entry entry : exparamsMap.entrySet()) {
                String key = entry.getKey().toString();
                Object value = entry.getValue();
                params.setParameter(key, value);
            }
        }

        if (isRelate != null && isRelate.equals("true")) {
            params.setParameter("isRelate", "true");
            if (!StringUtil.isBlank(parentid)) {
                params.setParameter("relateid", parentid);
            }
        } else {
            if (!StringUtil.isBlank(parentid)) {
                params.setParameter("relateid", parentid);
            }
            parentid = "";
        }

        if (parentid != null && !parentid.isEmpty())
            params.setParameter("parentid", parentid);
        if (viewid != null && !viewid.isEmpty())
            params.setParameter("viewid", viewid);

        DocumentProcess dProcess = RunTimeServiceManager.documentProcess(applicationId);
        Form form = null;
        IUser user = getWebUser();
        Document doc = null;
        if (items != null) {
            /**
             * 审批流程过程中很多操作步骤都是通过这个缓存来修复的.
             */
            Document temp = (Document) MemoryCacheUtil.getFromPrivateSpace(docId, user);
            if(temp==null) {
                temp = (Document) dProcess.doView(docId);
            }
            if (temp == null) {
                form = DesignTimeServiceManager.formDesignTimeService().doView(formid);
                temp = dProcess.doNew(form, user, params);
                temp.setId(docId);
            }

            for (Map.Entry<String, Object> entry : items.entrySet()) {
                String key = entry.getKey();
                Object value = entry.getValue();
                Item item = temp.findItem(key);

                if (item == null) {
                    if (!StringUtil.isBlank(key) && key.lastIndexOf("_show") > -1) {
                        item = temp.findItem(key.substring(0, key.lastIndexOf("_show")));
                    }
                }
                if (item != null) params.setParameter(key, value);
            }

            doc = temp;
        } else {
            return new Document();
        }

        if (!items.isEmpty() && isFromRefresh == null) {
            if (form == null) {
                form = DesignTimeServiceManager.formDesignTimeService().doView(formid);
            }

            doc = form.createDocument(doc, params, user);
        }

        if (!StringUtil.isBlank(parentid)) {
            doc.setParent(parentid);
        }
        if (!StringUtil.isBlank(stateid)) {
            doc.setState(stateid);
        }
        if (!StringUtil.isBlank(sign)) {
            doc.setSign(sign);
        }
        if (StringUtil.isBlank(doc.getFormid()) && !StringUtil.isBlank(formid)) {
            doc.setFormid(formid);
        }

        if (StringUtil.isBlank(doc.getApplicationid()) && !StringUtil.isBlank(applicationId)) {
            doc.setApplicationid(applicationId);
        }

        List<Document> subDocumentList = new ArrayList<Document>();
        if (subDocuments != null) {
            for (Iterator iterator = subDocuments.iterator(); iterator.hasNext(); ) {
                Map map = (Map) iterator.next();
                ParamsTable newParams = params.copyContextParams();
                Iterator<Map.Entry<String, Object>> iter = map.entrySet().iterator();
                while (iter.hasNext()) {
                    Map.Entry<String, Object> entry = iter.next();
                    String name = entry.getKey();
                    Object value = entry.getValue();
                    try {
                        if (value instanceof String[])
                            if (((String[]) value).length > 1)
                                newParams.setParameter(name, value);
                            else
                                newParams.setParameter(name, ((String[]) value)[0]);
                        else
                            newParams.setParameter(name, value);
                    } catch (Exception e) {
                        throw e;
                    }
                }

                Document subDoc = prepareDocument(net.sf.json.JSONObject.fromObject(map).toString(), applicationId, "$", newParams);
                subDocumentList.add(subDoc);
            }
        }
        doc.setSubDocuments(subDocumentList.isEmpty() ? null : subDocumentList);
        if (delete != null) {
            doc.setDelete(true);
        }
        if (edit != null) {
            doc.setEdit(true);
        }

        //设置回缓存
        /**
         * 执行中,后的操作将基于该doc
         */
        MemoryCacheUtil.putToPrivateSpace(doc.getId(), doc, getWebUser());

        return doc;
    }
}
