package com.horizon.workflow.support.service.impl;

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

import com.horizon.db.Access;
import com.horizon.extend.workflow.util.FlowJsonUtil;
import com.horizon.language.Hi18n;
import com.horizon.utils.StringUtil;
import com.horizon.wf.definition.json.JSONFlowInfo;
import com.horizon.wf.definition.pub.IFlowNode;
import com.horizon.workflow.support.model.FlowAuthor;
import com.horizon.workflow.support.model.FlowNextNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.horizon.common.base.Objects;
import com.horizon.core.HorizonCore;
import com.horizon.core.common.service.SpringContextHolder;
import com.horizon.utils.HorizonPorps;
import com.horizon.utils.json.JsonUtil;
import com.horizon.wf.IWorkResult;
import com.horizon.wf.IWorkflowOperator;
import com.horizon.wf.WorkflowFactory;
import com.horizon.wf.bean.WorkParaBean;
import com.horizon.wf.entity.db.DBLog;
import com.horizon.workflow.support.action.ActionContext;
import com.horizon.workflow.support.action.ActionStrategy;
import com.horizon.workflow.support.data.BusinessDataOperate;
import com.horizon.workflow.support.model.FlowAction;
import com.horizon.workflow.support.model.FlowResult;
import com.horizon.workflow.support.result.FlowBuilder;
import com.horizon.workflow.support.result.FlowDirector;
import com.horizon.workflow.support.service.IFlowSupportService;

/**
 * 流程操作实现类
 *
 * @author mwr
 */
@Service
public class FlowSupportServiceImpl implements IFlowSupportService {
    private static String WORKFLOW = "workflow";
    private final static Logger LOGGER = LoggerFactory.getLogger(FlowSupportServiceImpl.class);

    /*
     * 创建流程
     *
     * @see
     * com.horizon.workflow.support.service.IFlowSupportService#open(com.horizon
     * .wf.bean.WorkParaBean)
     */
    @Override
    public FlowResult create(WorkParaBean workParaBean) {
        IWorkflowOperator operator = WorkflowFactory.getWorkflowOperator();
        //IWorkflowOperator operator = WorkflowFactory.getWorkFlowOperator();
        // 流程创建是否提交到第一个结点
        String autoFirst = HorizonPorps.getConfig("workflow.autoFirstNode");
        boolean isNotFirst = Objects.equal(autoFirst, "false");
        workParaBean.setDoNotToFirstNode(isNotFirst);
        IWorkResult workResult = operator.create(workParaBean);
        FlowBuilder open = FlowDirector.INSTANCE.build(workResult);
        return open.getResult();
    }

    /*
     * 打开流程实例 (non-Javadoc)
     *
     * @see
     * com.horizon.workflow.support.service.IFlowSupportService#open(com.horizon
     * .wf.bean.WorkParaBean)
     */
    @Override
    public FlowResult open(WorkParaBean workParaBean) {
        IWorkflowOperator operator = WorkflowFactory.getWorkflowOperator();
        //IWorkflowOperator operator = WorkflowFactory.getWorkFlowOperator();
        IWorkResult workResult = operator.open(workParaBean);
        FlowBuilder open = FlowDirector.INSTANCE.build(workResult);
        return open.getResult();
    }

    /*
     * 流程操作
     *
     * @see
     * com.horizon.workflow.support.service.IFlowSupportService#operate(com.
     * horizon.wf.bean.WorkParaBean,
     * com.horizon.workflow.support.model.FlowAction)
     */
    @Override
    public String operate(WorkParaBean workParaBean, FlowAction action) {

        BusinessDataOperate baseRule = SpringContextHolder.getBean("bizDataOperate");
        workParaBean.setBussinessImpl(baseRule);
        ActionContext actionContext = new ActionContext();
        ActionStrategy strategy = actionContext.getActionStrategy(workParaBean, action);
        FlowAction newAction = strategy.actionDo();
        newAction.setSubjection(workParaBean.getSubjection());
        //2024-02-27 如果是仅允许选择人，则判断是否重新提交一次
        if ("submit".equals(action.getOperate()) && "0".equals(workParaBean.getSubmitflag())  && newAction.getStatus() == 4) {
            boolean isReSubmit = false;
            List<FlowNextNode> nextNodes = newAction.getNextNodes();
            //解析实例的建模
            List<IFlowNode> flowJsonNodes = FlowJsonUtil.getFlowJsonByWorkId(workParaBean.getWorkId(), HorizonCore.TENANT_IDENTIFIER.value());
            //循环所有节点的主办人，如果全部节点的selectauthor有人，则重新提交流程
            for (FlowNextNode nextNode : nextNodes) {
                String nextNodeId = nextNode.getNodeId();
                Map<String, FlowAuthor> authors = nextNode.getAuthors();
                FlowAuthor flowAuthor = authors.get("Author");
                if (null == flowAuthor) continue;
                boolean isOnlyUser = Boolean.parseBoolean(flowAuthor.getIsUser());
                //从实例建模里获取nextNodeId里主办是否配置了“需要从设置列表选择办理人”
                boolean isDefUser = FlowJsonUtil.getIsDefUser(nextNodeId, flowJsonNodes);
                isReSubmit = isOnlyUser && !isDefUser && StringUtil.hasValue(flowAuthor.getSelectAuthor());
                if (isReSubmit) {
                    Map<String, Object> otherPara = workParaBean.getOtherPara();
                    otherPara.put("actionData", JsonUtil.toJson(newAction));
                    workParaBean.setMemo("");//需设置为空，否则影响流程跟踪记录的操作内容
                    strategy = actionContext.getActionStrategy(workParaBean, newAction);
                    newAction = strategy.actionDo();
                    break;
                }
            }
        }
        //2024-02-27 end
        return newAction.toString();
    }


    /*
     * 关闭流程实例
     *
     * @see
     * com.horizon.workflow.support.service.IFlowSupportService#close(java.lang.
     * String, java.lang.String)
     */
    @Override
    public void close(String workId, String trackId, String userId) {

        if (!StringUtil.hasValue(workId) || !StringUtil.hasValue(trackId)) {
            LOGGER.error(Hi18n.getVal(WORKFLOW, "closeException"), workId, trackId);
            return;

        }
        // IWorkflowOperator operator = WorkflowFactory.getWorkFlowOperator();
        IWorkflowOperator operator = WorkflowFactory.getWorkflowOperator();
        operator.close(workId, trackId, userId, HorizonCore.TENANT_CODE.value());
    }

    /*
     * 流程历史记录
     *
     * @see
     * com.horizon.workflow.support.service.IFlowSupportService#getHistory(java.
     * lang.String)
     */
    @Override
    public String getHistory(String workId) {
        //IWorkflowOperator ica = WorkflowFactory.getWorkFlowOperator();
        IWorkflowOperator operator = WorkflowFactory.getWorkflowOperator();
        List<DBLog> logs = operator.getHistory(workId, HorizonCore.TENANT_IDENTIFIER.value());
        String jsonLog = null;
        if (logs != null && !logs.isEmpty()) {
            jsonLog = JsonUtil.toJson(logs);
        }
        return jsonLog;
    }

}
