package nckd.jimin.jyyy.bd.plugin.msg.ecology;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import kd.bos.bec.api.IEventServicePlugin;
import kd.bos.bec.model.EntityEvent;
import kd.bos.bec.model.JsonEvent;
import kd.bos.bec.model.KDBizEvent;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.dataentity.resource.ResManager;
import kd.bos.exception.ErrorCode;
import kd.bos.exception.KDException;
import kd.bos.logging.Log;
import kd.bos.logging.LogFactory;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.sdk.util.KHttpClientUtils;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import kd.bos.util.StringUtils;
import kd.bos.workflow.engine.WfUtils;
import kd.bos.workflow.engine.msg.ctx.MessageContext;
import kd.bos.workflow.engine.msg.info.MessageInfo;
import kd.bos.workflow.exception.WFErrorCode;
import kd.bos.workflow.exception.WFMessageServiceException;
import nckd.base.helper.CommonHelperUtils;
import org.apache.commons.lang3.ObjectUtils;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author wanghaiwu_kd
 * @date 2024/04/22
 * 插件说明：业务事件中心插件
 * 表单标识：消息阅读状态变更事件.执行插件(wf.AfterChangeMessageStateEvent.executePlugin)
 */
public class ChangeMessageStatePlugin implements IEventServicePlugin {
    private static Log logger = LogFactory.getLog(ChangeMessageStatePlugin.class);
    private static String KEY_ENTITY_LOG = "nckd_ecology";
    //
    private static String param_url = "";
    private static String param_msgurl = "";
    //注册企业id
    private static String param_cropid = "";
    private static String param_responsetype = "";
    private static String param_state = "";
    private static String param_appkey = "";
    private static String param_appsecret = "";
    private static String param_granttype = "";
    private static String param_secretkey = "";
    private static String param_syscode = "";
    private static String param_getcode = "";
    private static String param_gettoken = "";
    private static String param_sendflow = "";
    private static String param_receiver_dev = "";

    private static void setParmamValue(){
        String selectField = "nckd_entryentity.nckd_key, nckd_entryentity.nckd_value";

        QFilter qFilter = new QFilter("number", QCP.equals, "fanwei");
        DynamicObject commonParam = BusinessDataServiceHelper.loadSingle("nckd_commonparams", selectField, qFilter.toArray());
        if (ObjectUtils.isEmpty(commonParam)) {
            return;
        }

        DynamicObjectCollection entryentity = commonParam.getDynamicObjectCollection("nckd_entryentity");
        Map<String, String> mapentity = entryentity.stream().collect(Collectors.toMap(k -> k.getString("nckd_key"), v -> v.getString("nckd_value")));
        if(mapentity != null ){
            param_url = mapentity.get("url");
            param_msgurl = mapentity.get("msgurl");
            param_cropid = mapentity.get("corpid");
            param_responsetype = mapentity.get("response_type");
            param_state = mapentity.get("state");
            param_appkey = mapentity.get("app_key");
            param_appsecret = mapentity.get("app_secret");
            param_granttype = mapentity.get("grant_type");
            param_secretkey = mapentity.get("secret_key");
            param_syscode = mapentity.get("syscode");
            param_getcode = mapentity.get("getcode");

            param_gettoken = mapentity.get("gettoken");
            param_sendflow = mapentity.get("sendflow");
            param_receiver_dev = mapentity.get("receiver_dev");
        }
    }

    @Override
    public Object handleEvent(KDBizEvent evt) {
        logger.info("泛微消息阅读状态变更事件" + evt.toString());

        if (evt instanceof EntityEvent) {//苍穹事件
            EntityEvent entityEvent = (EntityEvent) evt;//类型转换
            String businesskey = entityEvent.getBusinesskeys().get(0);
            String entityNumber = entityEvent.getEntityNumber();
            DynamicObject obj = BusinessDataServiceHelper.loadSingle(businesskey, entityNumber);
            Long evtID = evt.getEventId();
            String source = evt.getSource();//传递的事件参数
        } else {//自定义事件
            JsonEvent jsonEvent = (JsonEvent) evt;//类型转换
            String source = jsonEvent.getSource();//传递的事件参数
            if (WfUtils.isNotEmpty(source)) {
                setParmamValue();

                if (StringUtils.isEmpty(param_sendflow)) {
                    logger.info("泛微消息阅读状态变更事件 is fail :未配置泛微参数sendflow!");

                    return null;
                }

                JSONArray arr = (JSONArray) JSON.parse(source);
                for (int i = 0; i < arr.size(); i++) {
                    if(arr.getJSONObject(i) == null) {
                        continue;
                    }
                    //消息id
                    String msgIds = arr.getJSONObject(i).getString("msgIds");

                    logger.info("泛微消息阅读状态变更事件:msgIds" + msgIds);

                    //用户id
                    String userId = arr.getJSONObject(i).getString("userId");
                    //状态
                    String state = arr.getJSONObject(i).getString("state");

                    if(StringUtils.isEmpty(msgIds)){
                        continue;
                    }

                    updateEcologyMsgState(userId, msgIds);
                }
            }
        }
        return null;
    }

    /**
     * 更新消息状态
     * @param userId
     * @param msgIds
     */
    private void updateEcologyMsgState(String userId, String msgIds){
        QFilter qFilter = new QFilter("id", QCP.equals, Long.valueOf(userId));
        //接收人员
        DynamicObject user = BusinessDataServiceHelper.loadSingle("bos_user", qFilter.toArray());
        String personNo = user.getString("number");

        msgIds = msgIds.replace("[", "").replace("]", "");
        String[] msgIdList = msgIds.split(",");
        if(msgIdList.length == 0){
            return;
        }

        for(String msgId : msgIdList){
            logger.info("泛微消息阅读状态变更事件:替换前 msgId：" + msgId);
            msgId = msgId.replace("\"", "");
            logger.info("泛微消息阅读状态变更事件:替换后msgId：" + msgId);

            qFilter = new QFilter("channel", QCP.equals, "fanwei");
            qFilter.and(new QFilter("messageid", QCP.equals, Long.valueOf(msgId)));
            DynamicObject msgFail = BusinessDataServiceHelper.loadSingle("wf_msg_failmessage", qFilter.toArray());

            if(msgFail == null){
                continue;
            }
            Long channelMsgId = msgFail.getLong("id");
            String tplscene = msgFail.getString("tplscene");
            String oaId = "";

            if("circulation".equals(tplscene)){
                oaId = "KD-" + channelMsgId + "-" + personNo;
            }

            sendMsg2Ecology(Long.valueOf(userId), Long.valueOf(msgId), oaId);
        }
    }

    private void sendMsg2Ecology(Long userId, Long msgId, String oaId){
        JSONObject fanweiBodyData = null;

        QFilter qFilter = new QFilter("nckd_oaid", QCP.equals, oaId);
        DynamicObject ecologyLog = BusinessDataServiceHelper.loadSingle("nckd_ecology", qFilter.toArray());

        if(ecologyLog == null){
            //根据消息Id组合OA消息对象
            fanweiBodyData = buildMessageBodyData(userId, msgId, oaId);
        } else {
            String sendData = ecologyLog.getString("nckd_senddata_tag");
            if(StringUtils.isEmpty(sendData)){

            } else {

                fanweiBodyData = JSONObject.parseObject(sendData);
            }
        }

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String createTime = sdf.format(new Date());
        String curTimestamp = String.valueOf(System.currentTimeMillis());


        //流程处理状态：0：待办，2：已办，4：办结，8：抄送（待阅）
        fanweiBodyData.put("isremark", "2");
        //流程查看状态：0：未读，1：已读
        fanweiBodyData.put("viewtype", "1");
        //接收时间
        fanweiBodyData.put("receivedatetime", createTime);
        //接收时间戳
        fanweiBodyData.put("receivets", curTimestamp);


        logger.info("消息阅读状态变更事件:" + fanweiBodyData.toString());


        String token = getFanWeiToken(false);
        String bodyString = "";
        String url = "";
        String result = "";

        Map<String, String> header = new HashMap<>();
        header.put("Content-Type", "application/json; charset=UTF-8");

        //获取token
        try {
            url = param_sendflow + "?access_token=" + token + "&secret_key=" + param_secretkey;
            logger.info("泛微发送消息接口地址：" + url);
            bodyString = CommonHelperUtils.buildEsbApiBodyJSON(fanweiBodyData);
            result = KHttpClientUtils.postjson(url, header, bodyString);
        } catch (IOException e) {
            logger.info(e.getMessage());

            String message = ResManager.loadKDString("泛微消息阅读状态更新失败，原因:%s", "WFErrorCode_10001", "bos-wf-engine", new Object[0]);
            ErrorCode error = new ErrorCode("bos.wf.rpa.", message);
            throw new WFMessageServiceException(e, error, new Object[]{e.getMessage()});
        }

        if(StringUtils.isEmpty(result)){
            logger.info("泛微消息阅读状态更新异常: 接口返回为空");
            throw new WFMessageServiceException("泛微消息阅读状态更新异常: 接口返回为空");
        }

        JSONObject msgObj = JSONObject.parseObject(result);
        if(msgObj.get("message") == null){
            logger.info("泛微消息阅读状态更新异常: 接口返回message为空");
//                    throw new WFMessageServiceException("创建泛微待办异常: 接口返回为空");
        }

        JSONObject message = msgObj.getJSONObject("message");
        if(message.get("errcode") == null){
            logger.info("泛微消息阅读状态更新异常: 接口返回errorcode为空");
//                    throw new WFMessageServiceException("创建泛微待办异常: 接口返回为空");
        }

        String code = message.getString("errcode");

        if(StringUtils.isNotEmpty(code) && "200".equals(code)){
            logger.info("泛微消息阅读状态更新失败 :" + message.getString("errmsg"));
        } else {
            logger.info("泛微消息阅读状态更新成功, 消息id: " + oaId);
        }


        logger.info("消息阅读状态变更事件，发送消息：{}, 结果：{}", fanweiBodyData.toJSONString(), result);
    }

    /**
     * 根据 messageid 构造OA消息对象
     * @param userId
     * @param msgId
     * @param oaId
     * @return
     */
    public static JSONObject buildMessageBodyData(Long userId, Long msgId, String oaId) {
        JSONObject bodyData = new JSONObject();

        String isremark = "2";
        String viewtype = "1";

        QFilter qFilter = new QFilter("id", QCP.equals, Long.valueOf(msgId));
        DynamicObject info = BusinessDataServiceHelper.loadSingle("wf_msg_message", qFilter.toArray());
        if(info == null){
            info = BusinessDataServiceHelper.loadSingle("wf_msg_himessage", qFilter.toArray());
        }

        if(info == null){
            return null;
        }


        String content = StringUtils.isEmpty(info.getString("content")) ?
                                info.getString("content_summary") : info.getString("content");
        if(content == null){
            content = info.getString("title") == null ? "" : info.getString("title");
        }

        if(content.indexOf("<br>意见：") >= 0) {
            content = content.substring(content.indexOf("<br>意见：") + 7);
        }

        //发送人员
        Long createUserId = 0L;
        if(info != null && !StringUtils.isEmpty(info.getString("sender"))){
            createUserId = Long.valueOf(info.getString("sender"));
        }

        DynamicObject createUser = BusinessDataServiceHelper.loadSingleFromCache(createUserId, "bos_user");
        String creator = createUser == null ? "" : createUser.getString("number");

//        String requestname = info.getString("title") + ", 发送人：" + creator + ", " + content;
        String requestname = content;

        String nodename = info.getString("operation") == null ? "circulation" : info.getString("operation");
        String workflowname = "费控人力审批流";
        String workflowcode = "nobill";

        if(info.getString("config") != null){
            JSONObject config = JSONObject.parseObject(info.getString("config"));
            if(config != null) {
                if(config.get("messageContext") != null){
                    JSONObject messageContext = JSONObject.parseObject(config.get("messageContext").toString());
                    if(messageContext.get("taskId") != null){
                        DynamicObject taskInfo = BusinessDataServiceHelper.loadSingleFromCache(Long.valueOf(messageContext.getString("taskId")), "wf_task");
                        if(taskInfo != null){
                            nodename = taskInfo.getString("name");

                            if(taskInfo.getLong("processdefinitionid") > 0){
                                qFilter = new QFilter("id", QCP.equals, taskInfo.getLong("processdefinitionid"));
                                DynamicObject processdef = BusinessDataServiceHelper.loadSingle("wf_processdefinition", qFilter.toArray());
                                if(processdef != null){
                                    workflowcode = processdef.getString("key");
                                    workflowname = processdef.getString("name");
                                }
                            }

                            if("费控人力审批流".equals(workflowname) && taskInfo.getString("entityname") != null){
                                workflowcode = taskInfo.getString("entityname");
                                workflowname = taskInfo.getString("entityname") + "审批流程";
                            }
                        }
                    }
                }
            }
        }

        //接收人员
        DynamicObject user = BusinessDataServiceHelper.loadSingleFromCache(userId, "bos_user");
        String personNo = user.getString("number");
        String receiverLong = user.getString("name") + "(" + user.getString("number") + ")";

        //创建时间
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String createTime = sdf.format(new Date());
        String curTimestamp = String.valueOf(System.currentTimeMillis());
        String flowid = oaId;

        String pcUrl = info.getString("contenturl") == null ? "" : info.getString("contenturl");
        String mobUrl = info.getString("mobcontenturl") == null ? pcUrl : info.getString("mobcontenturl");

        String contextUrl = System.getProperty("domain.contextUrl").replace("/ierp", "");
        pcUrl = pcUrl.replace("http://127.0.0.1:8080", "").replace(contextUrl, "");
        mobUrl = mobUrl.replace("http://127.0.0.1:8080", "").replace(contextUrl, "");

        logger.info("消息pcurl:" + pcUrl + ", moburl:" + mobUrl);

        //移动端需要走外网，将地址替换成外网地址
        String curUrl = "";//ParamsUtil.getCommonParamsField("nckd_url");
        String mobileUrl = "";//ParamsUtil.getCommonParamsField("nckd_mobileurl");

        if(StringUtils.isNotEmpty(pcUrl)){
            pcUrl = pcUrl.replace(mobileUrl, curUrl);
        }

        if(StringUtils.isNotEmpty(mobUrl)){
            mobUrl = mobUrl.replace(curUrl, mobileUrl);
        }

        if("".equals(pcUrl)||pcUrl==null){
            pcUrl = System.getProperty("domain.contextUrl")+"/index.html?formId=wf_msg_center";
        }

        try {
            pcUrl = pcUrl + "&msgId=" + msgId + "&closeType=closeWin";
            mobUrl = mobUrl + "&msgId=" + msgId + "&closeType=closeWin";

            pcUrl = URLEncoder.encode(pcUrl, "utf-8");
            mobUrl = URLEncoder.encode(mobUrl, "utf-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }

        //异构系统标识
        bodyData.put("syscode", param_syscode);
        //流程实例id
        bodyData.put("flowid", flowid);
        //标题
        bodyData.put("requestname", requestname);
        //流程类型编码
        bodyData.put("workflowcode", workflowcode);
        //流程类型名称
        bodyData.put("workflowname", workflowname);
        //接收人所属节点
        bodyData.put("receivenodename", "");
        //节点名称
        bodyData.put("nodename", nodename);
        //PC地址
        bodyData.put("pcurl", pcUrl);
        //APP地址
        bodyData.put("appurl", mobUrl);
        //创建人
        bodyData.put("creator", creator);
        //创建时间
        bodyData.put("createdatetime", createTime);
        //接收人
        bodyData.put("receiver", personNo);

        //测试人员
        if(StringUtils.isNotEmpty(param_receiver_dev)) {
            bodyData.put("receiver", param_receiver_dev);
        }

        //接收时间
        bodyData.put("receivedatetime", createTime);
        //流程处理状态：0：待办，2：已办，4：办结，8：抄送（待阅）
        bodyData.put("isremark", isremark);
        //流程查看状态：0：未读，1：已读
        bodyData.put("viewtype", viewtype);
        //接收时间戳
        bodyData.put("receivets", curTimestamp);
        //接收人+编码，保存日志使用，oa接口不需要此字段。
        bodyData.put("receiverLong", receiverLong);

        return bodyData;
    }

    /**
     * 获取泛微OA的accesstoken
     * @return
     */
    public static String getFanWeiToken(boolean isSerchParam) {
        if(isSerchParam){
            setParmamValue();
        }

        String bodyString = "";
        String token = "";
        String result = "";
        String url = "";

        Map<String, String> header = new HashMap<>();
        header.put("Content-Type", "application/json; charset=UTF-8");


        try {
            url = param_getcode + "?corpid=" + param_cropid + "&response_type=" + param_responsetype + "&state=" + param_state;

            logger.info("获取泛微code接口地址：" + url);
            //获取code
            bodyString = CommonHelperUtils.buildEsbApiBodyJSON(null);
            result = KHttpClientUtils.postjson(url, header, bodyString);
        } catch (Exception e) {
            logger.info(e.getMessage());

            String message = ResManager.loadKDString("获取泛微code失败，原因:%s", "WFErrorCode_10001", "bos-wf-engine", new Object[0]);
            ErrorCode error = new ErrorCode("bos.wf.rpa.", message);
            throw new WFMessageServiceException(e, error, new Object[]{e.getMessage()});
        }

        if(StringUtils.isEmpty(result)){
            throw new WFMessageServiceException("获取泛微code异常: 接口返回为空");
        }

        JSONObject codeObj = JSONObject.parseObject(result);
        String errcode = codeObj.getString("errcode");

        if(!"0".equals(errcode)) {
            String errCode = codeObj.getString("errcode") == null ? "" : codeObj.getString("errcode");
            String errMsg = codeObj.getString("errmsg") == null ? "" : codeObj.getString("errmsg");

            throw new WFMessageServiceException("获取泛微code异常: " + errMsg + "(" + errCode + ")");
        }
        String code = codeObj.getString("code");

        //获取token
        try {
            url = param_gettoken + "?app_key=" + param_appkey + "&app_secret=" + param_appsecret + "&grant_type=" + param_granttype + "&code=" + code;
            logger.info("获取泛微token接口地址：" + url);

            bodyString = CommonHelperUtils.buildEsbApiBodyJSON(null);

            result = KHttpClientUtils.postjson(url, header, bodyString);
        } catch (IOException e) {
            logger.info(e.getMessage());

            String message = ResManager.loadKDString("获取泛微token失败，原因:%s", "WFErrorCode_10001", "bos-wf-engine", new Object[0]);
            ErrorCode error = new ErrorCode("bos.wf.rpa.", message);
            throw new WFMessageServiceException(e, error, new Object[]{e.getMessage()});
        }

        if(StringUtils.isEmpty(result)){
            throw new WFMessageServiceException("获取泛微token异常: 接口返回为空");
        }

        JSONObject tokenObj = JSONObject.parseObject(result);
        errcode = tokenObj.getString("errcode");

        if(!"0".equals(errcode)) {
            String errCode = codeObj.getString("errcode") == null ? "" : codeObj.getString("errcode");
            String errMsg = codeObj.getString("errmsg") == null ? "" : codeObj.getString("errmsg");

            throw new WFMessageServiceException("获取泛微code异常: " + errMsg + "(" + errCode + ")");
        }
        token = tokenObj.getString("accessToken");

        return token;
    }

    /**
     *
     * @param url
     * @param bodyData
     * @return
     */
    public static JSONObject doPostByHttpClient(String url, JSONObject bodyData) {
        try {
            Map<String, String> headers = new HashMap();
            headers.put("Content-Type", "application/json; charset=utf-8");
            headers.put("Accept", "application/json");
            logger.info(String.format("url[%s],data[%s]", url, bodyData.toJSONString()));
            System.out.println(String.format("url[%s],data[%s]", url, bodyData.toJSONString()));

            String responseEntify = HttpUtils.postjson(url, headers, bodyData.toJSONString());
            JSONObject result = (JSONObject)JSONObject.parse(responseEntify);
            return result;
        } catch (IOException var5) {
            throw new KDException(var5, WFErrorCode.httpRequestException(), new Object[]{var5.getMessage()});
        }
    }
}
