package com.kingdee.eas.custom.weaverTodo;

import com.kingdee.bos.Context;
import com.kingdee.eas.base.message.MsgStatus;
import com.kingdee.eas.base.message.webservice.MessageWebServiceDao;
import com.kingdee.eas.base.message.webservice.WSMessage;
import com.kingdee.eas.base.message.webservice.WfrAssignMessage;
import com.kingdee.eas.base.message.webservice.WfrProcMessage;
import com.kingdee.eas.custom.weaverTodo.client.WeaverOpenApiTokenManager;
import com.kingdee.eas.custom.weaverTodo.client.WeaverReceiveTodoClient;
import com.kingdee.eas.custom.weaverTodo.client.WeaverSendMsgClient;
import com.kingdee.eas.custom.weaverTodo.config.WeaverTodoConfig;
import com.kingdee.eas.custom.weaverTodo.server.WeaverToBeReadMessageServer;
import com.kingdee.eas.custom.weaverTodo.server.WeaverTodoMessageServer;
import com.kingdee.eas.custom.weaverTodo.util.WeaverPushTrace;
import com.kingdee.eas.custom.weaverTodo.util.WeaverTodoSupport;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

/**
 * 平台 MessageWebServiceDao：流程待办走统一待办；BMC 通知走消息中心 sendMsg。
 *
 * 平台触发（据 bs_message-server MCInvoke + WfMsgToOtherSys）：
 * - AssignReadListener 新建任务 -> addMessage（任务）
 * - 任务完成/取消 -> addCompletedMessage
 * - 任务删除 -> removeMessage
 * - BMC 新建钩子 -> updateMessages(UNREADED) -> sendMsg
 * - addMessage 且 type=通知 -> 跳过（避免再推 isremark=0）
 *
 * coyle
 * 20260714
 */
public class WeaverMessageWebServiceDao implements MessageWebServiceDao {
    private static final Logger logger = Logger.getLogger(WeaverMessageWebServiceDao.class);

    private volatile WeaverTodoConfig config;
    private volatile WeaverTodoMessageServer todoServer;
    private volatile WeaverToBeReadMessageServer toBeReadServer;

    private void initIfNecessary() {
        WeaverTodoConfig latest = WeaverTodoConfig.getInstance();
        if (config == latest && todoServer != null && toBeReadServer != null) {
            return;
        }
        synchronized (this) {
            latest = WeaverTodoConfig.getInstance();
            if (config == latest && todoServer != null && toBeReadServer != null) {
                return;
            }
            try {
                WeaverTodoSupport support = new WeaverTodoSupport(latest);
                WeaverOpenApiTokenManager tokenManager = new WeaverOpenApiTokenManager(latest);
                WeaverReceiveTodoClient todoClient = new WeaverReceiveTodoClient(latest, tokenManager);
                WeaverSendMsgClient sendMsgClient = new WeaverSendMsgClient(latest, tokenManager);
                this.todoServer = new WeaverTodoMessageServer(latest, support, todoClient);
                this.toBeReadServer = new WeaverToBeReadMessageServer(latest, support, sendMsgClient);
                this.config = latest;
                logger.info("[WEAVER-TODO] Dao 初始化完成 enabled=" + latest.isEnabled()
                        + " syscode=" + latest.getSyscode()
                        + " sendMsg=" + latest.getSendMsgPath());
            } catch (Exception e) {
                logger.error("[WEAVER-TODO] Dao 初始化失败，推送禁用", e);
                this.config = null;
                this.todoServer = null;
                this.toBeReadServer = null;
            }
        }
    }

    private boolean guardEnabled(String spi, String traceId) {
        initIfNecessary();
        if (config == null || !config.isEnabled() || todoServer == null) {
            logger.warn("[WEAVER-TODO][" + traceId + "] SPI=" + spi
                    + " 跳过：未启用或未初始化 enabled="
                    + (config == null ? "null" : String.valueOf(config.isEnabled())));
            return false;
        }
        return true;
    }

    private static boolean isNotifyType(WSMessage message) {
        if (message == null || message.getType() == null) {
            return false;
        }
        String alias = message.getType().getAlias();
        return StringUtils.isNotBlank(alias) && alias.contains("通知");
    }

    @Override
    public boolean addMessage(WSMessage message) {
        String traceId = WeaverPushTrace.nextId();
        logger.info("[WEAVER-TODO][" + traceId + "] SPI=addMessage ENTER"
                + " tip=通常=工作流新任务；通知类应跳过"
                + " msgId=" + (message == null ? null : message.getMsgID())
                + " procInstId=" + (message == null ? null : message.getProcInstId())
                + " billId=" + (message == null ? null : message.getBillId())
                + " title=" + (message == null ? null : message.getTitle())
                + " type=" + (message == null || message.getType() == null ? null : message.getType().getAlias())
                + " bizType=" + (message == null || message.getBizType() == null ? null : message.getBizType().getAlias())
                + " recieverID=" + (message == null ? null : message.getRecieverID())
                + " recieveNumber=" + (message == null ? null : message.getRecieveNumber())
                + " receivers=" + (message == null ? null : message.getReceivers())
                + " senderNumber=" + (message == null ? null : message.getSenderNumber())
                + " actName=" + (message == null ? null : message.getActName())
                + " expectIsremark=0(待办)"
                + " caller=" + WeaverPushTrace.callerHint());
        if (!guardEnabled("addMessage", traceId)) {
            return false;
        }
        if (isNotifyType(message)) {
            logger.info("[WEAVER-TODO][" + traceId + "] SPI=addMessage 跳过：type=通知，改由 BMC updateMessages->sendMsg");
            return true;
        }
        boolean ok = todoServer.addMessage(message, traceId);
        logger.info("[WEAVER-TODO][" + traceId + "] SPI=addMessage EXIT ok=" + ok);
        return ok;
    }

    @Override
    public boolean addCompletedMessage(WfrAssignMessage wfrAssignMessage) {
        String traceId = WeaverPushTrace.nextId();
        logger.info("[WEAVER-TODO][" + traceId + "] SPI=addCompletedMessage ENTER"
                + " tip=通常=任务完成或CANCELED(重新指定/撤销仍会调此方法)"
                + " assignId=" + (wfrAssignMessage == null ? null : wfrAssignMessage.getAssignId())
                + " procInstId=" + (wfrAssignMessage == null ? null : wfrAssignMessage.getProcInstId())
                + " billId=" + (wfrAssignMessage == null ? null : wfrAssignMessage.getBillID())
                + " billNumber=" + (wfrAssignMessage == null ? null : wfrAssignMessage.getBillNumber())
                + " subject=" + (wfrAssignMessage == null ? null : wfrAssignMessage.getAssignSubject())
                + " assignState=" + (wfrAssignMessage == null ? null : wfrAssignMessage.getState())
                + " assignStateName=" + (wfrAssignMessage == null ? null : wfrAssignMessage.getStateName())
                + " handler=" + (wfrAssignMessage == null ? null : wfrAssignMessage.getHandler())
                + " handlerNumber=" + (wfrAssignMessage == null ? null : wfrAssignMessage.getHandlerNumber())
                + " handlerId=" + (wfrAssignMessage == null ? null : wfrAssignMessage.getHandlerId())
                + " initiatorNumber=" + (wfrAssignMessage == null ? null : wfrAssignMessage.getInitiatorNumber())
                + " actName=" + (wfrAssignMessage == null ? null : wfrAssignMessage.getActName())
                + " expectIsremark=COMPLETED->2 / CANCELED->-1 / 终结流程再推4"
                + " caller=" + WeaverPushTrace.callerHint());
        if (!guardEnabled("addCompletedMessage", traceId)) {
            return false;
        }
        boolean ok = todoServer.addCompletedMessage(wfrAssignMessage, traceId);
        logger.info("[WEAVER-TODO][" + traceId + "] SPI=addCompletedMessage EXIT ok=" + ok);
        return ok;
    }

    @Override
    public boolean removeMessage(String assignId, Context context) {
        String traceId = WeaverPushTrace.nextId();
        logger.info("[WEAVER-TODO][" + traceId + "] SPI=removeMessage(ctx) ENTER"
                + " tip=通常=任务删除/wsImplRemoveAss；BMC删除也可能走进来"
                + " assignId=" + assignId
                + " hasCtx=" + (context != null)
                + " ais=" + (context == null ? null : context.getAIS())
                + " expectIsremark=-1(删除)"
                + " caller=" + WeaverPushTrace.callerHint());
        if (!guardEnabled("removeMessage(ctx)", traceId)) {
            return false;
        }
        boolean ok = todoServer.removeMessage(assignId, context, traceId);
        logger.info("[WEAVER-TODO][" + traceId + "] SPI=removeMessage(ctx) EXIT ok=" + ok);
        return ok;
    }

    @Override
    public boolean removeMessage(String assignId) {
        String traceId = WeaverPushTrace.nextId();
        logger.info("[WEAVER-TODO][" + traceId + "] SPI=removeMessage(noCtx) ENTER"
                + " tip=无Context重载，内部转 removeMessage(ctx=null)"
                + " assignId=" + assignId
                + " expectIsremark=-1(删除)"
                + " caller=" + WeaverPushTrace.callerHint());
        if (!guardEnabled("removeMessage(noCtx)", traceId)) {
            return false;
        }
        boolean ok = todoServer.removeMessage(assignId, null, traceId);
        logger.info("[WEAVER-TODO][" + traceId + "] SPI=removeMessage(noCtx) EXIT ok=" + ok);
        return ok;
    }

    @Override
    public boolean updateMessages(String id, MsgStatus msgStatus, Context ctx) {
        String traceId = WeaverPushTrace.nextId();
        logger.info("[WEAVER-TODO][" + traceId + "] SPI=updateMessages(ctx) ENTER"
                + " tip=BMC新建未读走 sendMsg"
                + " id=" + id
                + " msgStatus=" + (msgStatus == null ? null : msgStatus.getAlias())
                + " msgStatusValue=" + (msgStatus == null ? null : String.valueOf(msgStatus.getValue()))
                + " hasCtx=" + (ctx != null)
                + " caller=" + WeaverPushTrace.callerHint());
        if (!guardEnabled("updateMessages(ctx)", traceId)) {
            return false;
        }
        boolean ok = toBeReadServer.handleToBeReadMessage(id, msgStatus, ctx, traceId);
        logger.info("[WEAVER-TODO][" + traceId + "] SPI=updateMessages(ctx) EXIT ok=" + ok);
        return ok;
    }

    @Override
    public boolean updateMessages(String id, MsgStatus msgStatus) {
        String traceId = WeaverPushTrace.nextId();
        logger.info("[WEAVER-TODO][" + traceId + "] SPI=updateMessages(noCtx) ENTER"
                + " tip=无Context重载，内部转 updateMessages(ctx=null)"
                + " id=" + id
                + " msgStatus=" + (msgStatus == null ? null : msgStatus.getAlias())
                + " caller=" + WeaverPushTrace.callerHint());
        if (!guardEnabled("updateMessages(noCtx)", traceId)) {
            return false;
        }
        boolean ok = toBeReadServer.handleToBeReadMessage(id, msgStatus, null, traceId);
        logger.info("[WEAVER-TODO][" + traceId + "] SPI=updateMessages(noCtx) EXIT ok=" + ok);
        return ok;
    }

    @Override
    public boolean updateMessage(String id) {
        String traceId = WeaverPushTrace.nextId();
        logger.info("[WEAVER-TODO][" + traceId + "] SPI=updateMessage(noCtx) ENTER"
                + " tip=平台 wsImplUpdate 单条更新，本实现暂不推泛微"
                + " id=" + id
                + " action=NOOP return=false"
                + " caller=" + WeaverPushTrace.callerHint());
        return false;
    }

    @Override
    public boolean updateMessage(String id, Context context) {
        String traceId = WeaverPushTrace.nextId();
        logger.info("[WEAVER-TODO][" + traceId + "] SPI=updateMessage(ctx) ENTER"
                + " tip=平台 wsImplUpdate 单条更新，本实现暂不推泛微"
                + " id=" + id
                + " hasCtx=" + (context != null)
                + " action=NOOP return=false"
                + " caller=" + WeaverPushTrace.callerHint());
        return false;
    }

    @Override
    public boolean addInitiatorMessage(WfrProcMessage wfrProcMessage) {
        String traceId = WeaverPushTrace.nextId();
        logger.info("[WEAVER-TODO][" + traceId + "] SPI=addInitiatorMessage ENTER"
                + " tip=流程实例推送(wsImplReadMyProcInfo)；本实现暂不推泛微"
                + " procInstId=" + (wfrProcMessage == null ? null : wfrProcMessage.getProcInstId())
                + " procCode=" + (wfrProcMessage == null ? null : wfrProcMessage.getProcCode())
                + " procSubject=" + (wfrProcMessage == null ? null : wfrProcMessage.getProcSubject())
                + " procState=" + (wfrProcMessage == null ? null : wfrProcMessage.getProcState())
                + " procStateName=" + (wfrProcMessage == null ? null : wfrProcMessage.getProcStateName())
                + " billId=" + (wfrProcMessage == null ? null : wfrProcMessage.getBillID())
                + " billNumber=" + (wfrProcMessage == null ? null : wfrProcMessage.getBillNumber())
                + " initiatorNumber=" + (wfrProcMessage == null ? null : wfrProcMessage.getInitiatorNumber())
                + " initiatorId=" + (wfrProcMessage == null ? null : wfrProcMessage.getInitiatorId())
                + " isAdd=" + (wfrProcMessage == null ? null : Integer.valueOf(wfrProcMessage.getIsAdd()))
                + " action=NOOP return=false"
                + " caller=" + WeaverPushTrace.callerHint());
        return false;
    }
}
