package com.horizon.workflow.support.action;

import com.horizon.common.base.Joiner;
import com.horizon.common.base.Objects;
import com.horizon.common.base.Splitter;
import com.horizon.common.collect.Lists;
import com.horizon.common.collect.Maps;
import com.horizon.core.HorizonCore;
import com.horizon.language.Hi18n;
import com.horizon.third.Authority;
import com.horizon.third.Organization;
import com.horizon.third.ThirdAdapterFactory;
import com.horizon.third.adapter.WorkflowBaseAdapther;
import com.horizon.third.entity.User;
import com.horizon.third.init.WorkflowAdapterInit;
import com.horizon.utils.HorizonPorps;
import com.horizon.utils.StringUtil;
import com.horizon.wf.core.node.INextNode;
import com.horizon.wf.global.StaticVarExtend;
import com.horizon.workflow.support.model.FlowAction;
import com.horizon.workflow.support.model.FlowAuthor;
import com.horizon.workflow.support.model.FlowNextNode;
import com.horizon.workflow.support.util.ActionUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

import static com.horizon.wf.global.StaticVarExtend.*;

/**
 * 流程基本提交操作（submit）
 *
 * @author mwr
 *
 */
public class DefaultSubmitAction extends ActionBaseStrategy {

    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultSubmitAction.class);

    @Override
    public FlowAction actionDo() {

        int status = operator();
        switch (status) {
            case StaticVarExtend.F_STATUS_SelectAuthor:
                setSelectUser();
                break;
            case StaticVarExtend.F_STATUS_SelectNode:
                setSelectNode();
                break;
            case StaticVarExtend.F_STATUS_Success:
                operateSuccess();
                break;
            case StaticVarExtend.F_STATUS_NoAuthor:
                setSelectDefUser();
                break;
            default:
                action.setOperateMsg(message());
                action.setOperateStatus("error");
                break;

        }
        action.setTrackId(trackId());
        action.setWorkId(workId());
        return action;
    }

    protected void setSelectDefUser() {

        String openDefAuthor = HorizonPorps.getConfig("workflow.openDefAuthor");
        if (Objects.equal(openDefAuthor, "true")) {
            String tenantCode = HorizonCore.TENANT_CODE.value();
            Authority authority = ThirdAdapterFactory.instanse(tenantCode).getAuthorityInstance();
            String selectAuthorId = authority.getManager(workParaBean.getFlowId());
            if (!StringUtil.hasValue(selectAuthorId)) {
                LOGGER.error("属性workflow.openDefAuthor设置为true，流程 [{}] 并未设置管理员", workParaBean.getFlowId());
                String message = message() + Hi18n.getVal(LANGUAGE_WORKFLOW,"notice") + getNonExistedAuthorNextNodes();
                action.setOperateMsg(message);
                action.setOperateStatus("error");
            } else {
                // 在没有办理人时，根据配置项设置默认办理人
                action.setNextNodes(getNextNodes());
                action.setOperateMsg(Hi18n.getVal(LANGUAGE_WORKFLOW,"notSelectUser"));
                action.setOperateFlag(StaticVarExtend.Submit_Flag_Commit);
            }
        } else {
            String message = message() + Hi18n.getVal(LANGUAGE_WORKFLOW,"notice") + getNonExistedAuthorNextNodes();
            action.setOperateMsg(message);
            action.setOperateStatus("error");
        }
    }
    @Override
    protected Map<String, FlowAuthor> getNextNodeAuthors(FlowNextNode flowNextNode) {

        int result = Integer.parseInt(flowNextNode.getNodeStatus());
        Map<String, FlowAuthor> authors = null;
        String openDefAuthor = HorizonPorps.getConfig("workflow.openDefAuthor");
        if ((result == StaticVarExtend.F_STATUS_NoAuthor) && Objects.equal(openDefAuthor, "true")) {
            authors = getDefaultAuthor(flowNextNode);
        } else {
            authors = super.getNextNodeAuthors(flowNextNode);
        }
        return authors;
    }

    private Map<String, FlowAuthor> getDefaultAuthor(FlowNextNode flowNextNode) {

        Map<String, FlowAuthor> authors = Maps.newHashMap();
        String tenantCode = HorizonCore.TENANT_CODE.value();
        Organization organization = ThirdAdapterFactory.instanse(tenantCode).getOrganizationInstance();
        Authority authority = ThirdAdapterFactory.instanse(tenantCode).getAuthorityInstance();
        String managerId = authority.getManager(workParaBean.getFlowId());
        List<String> authorIds = getSelectAuthorId(managerId);
        String selectAuthorId = Joiner.on(";").join(authorIds);
        String selectAuthorName = organization.getNameByIds(managerId, tenantCode);
        String selectType = getSelectType(flowNextNode.getNodeId(), StaticVarExtend.AUTH_AUTHOR);

        FlowAuthor flowAuthor = new FlowAuthor();
        flowAuthor.setAuthorId(StaticVarExtend.AUTH_AUTHOR);
        flowAuthor.setAuthorName(getAuhorName(StaticVarExtend.AUTH_AUTHOR));
        flowAuthor.setSelectType(selectType);

        if (authorIds.size() == 1) {
            flowAuthor.setIsDefUser("false");
            flowAuthor.setIsSelect("false");
            flowAuthor.setSelectAuthor(selectAuthorId);
            flowAuthor.setSelectAuthorName(selectAuthorName);
        } else {
            if (Objects.equal(selectType, "radio")) {
                flowAuthor.setIsDefUser("true");
                flowAuthor.setIsSelect("true");
                flowAuthor.setInitAuthor(ActionUtil.getAuthorMultimap(selectAuthorId, false));
            } else {
                flowAuthor.setIsDefUser("true");
                flowAuthor.setIsSelect("true");
                flowAuthor.setSelectAuthor(selectAuthorId);
                flowAuthor.setSelectAuthorName(selectAuthorName);
                flowAuthor.setInitAuthor(ActionUtil.getAuthorMultimap(selectAuthorId, false));
            }
        }
        flowAuthor.setIsUser("false");
        flowAuthor.setIsFree("false");
        authors.put(StaticVarExtend.AUTH_AUTHOR, flowAuthor);
        return authors;
    }

    private List<String> getSelectAuthorId(String managerId) {

        List<String> authorIds = Lists.newArrayList();
        List<String> list = Splitter.on(";").omitEmptyStrings().splitToList(managerId);
        if (list != null && !list.isEmpty()) {
            for (String id : list) {
                if (id.indexOf('_') < 0) {
                    id = "U_" + id;
                }
                authorIds.add(id);
            }
        }
        return authorIds;
    }

    /**
     * 一下节点办理人为自己时，自动打开流程，
     */
    @Override
    protected boolean autoOpen() {

        boolean isOpen = false;
        if (super.autoOpen()) {
            List<INextNode> nextNodes = workResult.getNextNodes();
            if (nextNodes != null) {
                for (INextNode nextNode : nextNodes) {
                    String nodeKey = nextNode.getKeyid();
                    String authorId = getSelectAuthor(nodeKey + "-Author");
                    isOpen = hasNextAuthor(authorId);
                }
            }
        }
        return isOpen;
    }
    @Override
    protected String getNextNodeGroup(INextNode nextNode) {

        String nodeGroup = null;
        String actionName = workResult.getWorkParaBean().getFunname();
        if (Objects.equal(actionName.toLowerCase(), OPERATOR_FUNNAME_JUMP_REJECT.toLowerCase())
                || Objects.equal(actionName.toLowerCase(), OPERATOR_FUNNAME_GOTO.toLowerCase())) {

            nodeGroup = "Node0";
        } else {
            nodeGroup = StringUtil.null2Empty(nextNode.getGroupName());
        }
        return nodeGroup;
    }
    @Override
    protected void setSelectAuthors(FlowAuthor flowAuthor, String authorKey) {

        super.setSelectAuthors(flowAuthor, authorKey);
        String initAuthor = getInitAuthor(authorKey);
        boolean isOnlyUser = Boolean.parseBoolean(flowAuthor.getIsUser());
        if (isOnlyUser && StringUtil.hasValue(initAuthor)) {
            String tenantCode = workResult.getWorkParaBean().getTenantCode();
            Organization organization = ThirdAdapterFactory.instanse(tenantCode).getOrganizationInstance();
            WorkflowBaseAdapther adapther = WorkflowAdapterInit.getWorkflowAdapthers("orgs");
            List<String> idList = Splitter.on(";").omitEmptyStrings().splitToList(initAuthor);
            List<String> userIds = Lists.newArrayList();
            for (String userId : idList) {
                String type = ActionUtil.getType(userId);
                if (!Objects.equal("U", type)) {
                    String orgId = ActionUtil.replaceId(userId);
                    List<User> users = adapther.findUserByOrgId(type, orgId);
                    if (users != null || !users.isEmpty()) {
                        for (User user : users) {
                            String fixId = user.getFixId() + "/" + type.toUpperCase()+ "_" +orgId;
                            userIds.add(fixId);
                        }
                    }
                } else {
                    userIds.add(userId);
                }
            }
            if (Objects.equal("radio", flowAuthor.getSelectType()) && userIds.size() == 1) {
                String selectId = Joiner.on(";").join(userIds.iterator());
                String selectName = organization.getNameByIds(selectId, null);
                flowAuthor.setSelectAuthorName(selectName);
                flowAuthor.setSelectAuthor(selectId);
            } else if (Objects.equal("checkbox", flowAuthor.getSelectType()) && userIds.size() <= 20) {
                String selectId = Joiner.on(";").join(userIds.iterator());
                String selectName = organization.getNameByIds(selectId, null);
                flowAuthor.setSelectAuthorName(selectName);
                flowAuthor.setSelectAuthor(selectId);
            }

        }
    }

    /**
     * 提交操作时，如果是当前节点，移除协办和读者的办理人设置
     */
    private void removeAuthors() {

        List<FlowNextNode> nextNodes = action.getNextNodes();
        if (nextNodes == null || nextNodes.isEmpty()) {
            return;
        }
        for (FlowNextNode nextNode : nextNodes) {
            if (Objects.equal(nextNode.getNodeId(), nextNode.getSelectId())) {
                Map<String, FlowAuthor> authorMap = nextNode.getAuthors();
                authorMap.remove(AUTH_SECOND_AUTHOR);
                authorMap.remove(AUTH_READER);
            }
        }
    }

    /**
     * 提交操作成功
     */
    private void operateSuccess() {

        String submitFlag = submitFlag();
        action.setNextNodes(getNextNodes());
        if (Objects.equal(submitFlag, "1")) {
            action.setOperateMsg(Hi18n.getVal(LANGUAGE_WORKFLOW,"nextNodeAuthor"));
            action.setOperateFlag(StaticVarExtend.Submit_Flag_Commit);
            removeAuthors();
        } else {
            action.setOperateMsg(message());
            action.setOperateStatus("success");
            action.setReOpen(String.valueOf(autoOpen()));
        }
    }

    /**
     * 选择人员
     */
    private void setSelectUser() {

        action.setNextNodes(getNextNodes());
        action.setOperateMsg(message());
        action.setOperateFlag(StaticVarExtend.Submit_Flag_Commit);
    }

    /**
     * 选择节点
     */
    private void setSelectNode() {

        // 设置节点
        List<FlowNextNode> nextNodes = getNextNodes();
        if (nextNodes == null || nextNodes.isEmpty()) {
            action.setOperateMsg(Hi18n.getVal(LANGUAGE_WORKFLOW,"notGetFlowNodeList"));
            action.setOperateStatus("error");
        } else {
            action.setNextNodes(getNextNodes());
            action.setOperateMsg(message());
            action.setOperateFlag(StaticVarExtend.Submit_Flag);
        }
    }
}
