package cn.axzo.workflow.core.util;

import cn.axzo.workflow.common.model.NextNodePreCheckAlterDTO;
import cn.axzo.workflow.common.model.dto.AlterDTO;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiRobotSendRequest;
import com.dingtalk.api.response.OapiRobotSendResponse;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static cn.azxo.framework.common.constatns.Constants.CTX_LOG_ID_MDC;

/**
 * 钉钉告警处理
 *
 * @author wangli
 * @since 2024/1/12 14:34
 */
@Slf4j
public class DingTalkUtils {

    private static final String dingtalk_robot_webhook = "https://oapi.dingtalk" +
            ".com/robot/send?access_token=341ee2907f3ebc15dc495fb7771a646230058710999fec7838066c109849878e";

    private static final Map<String, String> ENV_URL_MAPPING = new HashMap<>();
    private static final Map<String, String> WEB_URL_MAPPING = new HashMap<>();

    static {
        ENV_URL_MAPPING.put("local", "https://dev-app.axzo.cn");
        ENV_URL_MAPPING.put("dev", "https://dev-app.axzo.cn");
        ENV_URL_MAPPING.put("test", "https://test-api.axzo.cn");
        ENV_URL_MAPPING.put("pre", "https://pre-api.axzo.cn");
        ENV_URL_MAPPING.put("live", "https://live-api.axzo.cn");
        ENV_URL_MAPPING.put("default", "https://api.axzo.cn");

        WEB_URL_MAPPING.put("local", "https://dev-new-workflow-web.axzo.cn");
        WEB_URL_MAPPING.put("dev", "https://dev-new-workflow-web.axzo.cn");
        WEB_URL_MAPPING.put("test", "https://test-new-workflow-web.axzo.cn");
        WEB_URL_MAPPING.put("pre", "https://pre-new-workflow-web.axzo.cn");
        WEB_URL_MAPPING.put("live", "https://live-new-workflow-web.axzo.cn");
        WEB_URL_MAPPING.put("default", "https://new-workflow-web.axzo.cn");
    }

    public static String getEnvUrl(String profile) {
        String urlPrefix = ENV_URL_MAPPING.get(profile);
        if (!StringUtils.hasText(urlPrefix)) {
            urlPrefix = ENV_URL_MAPPING.get("default");
        }
        return urlPrefix;
    }

    public static String getWebUrl(String profile) {
        String urlPrefix = WEB_URL_MAPPING.get(profile);
        if (!StringUtils.hasText(urlPrefix)) {
            urlPrefix = WEB_URL_MAPPING.get("default");
        }
        return urlPrefix;
    }

    @SneakyThrows
    public static void sendDingTalk(String profile, String title, Object req, String invokeServerName, Throwable throwable) {
        OapiRobotSendRequest request = new OapiRobotSendRequest();
        request.setMsgtype("markdown");
        OapiRobotSendRequest.Markdown markdown = new OapiRobotSendRequest.Markdown();
        markdown.setTitle("Notice " + title + ", Env: " + profile);
        String text = "#### [" + profile + "]" + title + "\n" +
                "> 时间: " + DateUtil.now() + "\n" +
                "> 入参: " + JSONUtil.toJsonStr(req) + "\n\n" +
                "> ###### 异常信息: " + JSONUtil.toJsonStr(Objects.isNull(throwable.getCause()) ? throwable.getMessage() :
                throwable.getCause().getMessage()) + " \n\n" +
                "> ##### traceId: " + MDC.get(CTX_LOG_ID_MDC) + " \n" +
                "> ##### 调用方服务名称：" + invokeServerName + " \n";
        String deadLetterStacktrace = getDeadLetterStacktrace(profile, req);
        text = text + (StringUtils.hasText(deadLetterStacktrace) ? "> ##### [点击查看异常明细](" + deadLetterStacktrace + ") \n" : "");
        markdown.setText(text);
        request.setMarkdown(markdown);
        sendDingTalk(request);
    }

    private static String getDeadLetterStacktrace(String profile, Object req) {
        try {
            JSONObject entries = JSONUtil.parseObj(req);
            String jobId = entries.getStr("id");
            if (!StringUtils.hasText(jobId)) {
                return "";
            }
            return getEnvUrl(profile) + "/workflow-engine/web/v1/api/process/job/dead-letter/exception/stacktrace/byId?jobId=" + jobId;
        } catch (Exception e) {
            log.warn("构造查询错误堆栈地址异常", e);
            return "";
        }
    }

    @SneakyThrows
    public static void sendDingTalkForSlowUrl(String profile, Double time, String apiUrl, Object requestParam, Object responseBody) {
        OapiRobotSendRequest request = new OapiRobotSendRequest();
        request.setMsgtype("markdown");
        OapiRobotSendRequest.Markdown markdown = new OapiRobotSendRequest.Markdown();
        markdown.setTitle("Notice 请求二方接口慢 URL, Env: " + profile);
        markdown.setText("#### [" + profile + "]请求二方接口过慢\n" +
                "> 接口地址: " + apiUrl + ",经过了" + time + "秒\n\n" +
                "> 请求参数: " + JSONUtil.toJsonStr(requestParam) + "\n\n" +
                "> ###### 结果: " + JSONUtil.toJsonStr(responseBody) + " \n");
        request.setMarkdown(markdown);
        sendDingTalk(request);
    }

    @SneakyThrows
    public static void sendDingTalkForSlowApi(String profile, Double time, String apiUrl, String uniqueId) {
        OapiRobotSendRequest request = new OapiRobotSendRequest();
        request.setMsgtype("markdown");
        OapiRobotSendRequest.Markdown markdown = new OapiRobotSendRequest.Markdown();
        markdown.setTitle("Notice API 处理耗时报告, Env: " + profile);
        markdown.setText("#### [" + profile + "]API 处理耗时报告\n" +
                "> 接口地址: " + apiUrl + ",经过了" + time + "秒\n\n" +
                "> ###### 标识: " + uniqueId + " \n");
        request.setMarkdown(markdown);
        sendDingTalk(request);
    }

    @SneakyThrows
    private static void sendDingTalk(OapiRobotSendRequest request) {
        DingTalkClient client = new DefaultDingTalkClient(dingtalk_robot_webhook);
        OapiRobotSendResponse response = client.execute(request);
    }

    public static void sendDingTalkForBizNodeAlter(String profile, AlterDTO alterDTO, List<String> atMobiles) {
//        if (CollectionUtils.isEmpty(atMobiles)) {
//            return;
//        }
        String processInstanceId = alterDTO.getProcessInstanceId();
        OapiRobotSendRequest request = new OapiRobotSendRequest();
        request.setMsgtype("markdown");
        OapiRobotSendRequest.Markdown markdown = new OapiRobotSendRequest.Markdown();
        markdown.setTitle("Notice 业务节点长时间停止告警, Env: " + profile);
        markdown.setText("#### [" + profile + "]业务节点长时间停止\n" +
                "> 审批业务: " + alterDTO.getProcessDefinitionName() + "(" + alterDTO.getProcessDefinitionKey() + ")" + "\n\n" +
                "> 节点相关信息: " + JSONUtil.toJsonStr(alterDTO) + "\n\n" +
                "> ##### [点击查看审批日志](" + getWebUrl(profile) + "/#/workflow/examples?processInstanceId=" + processInstanceId + ") \n\n" +
                "> ##### 提示：如果以上地址提示未登录，请在对应环境 OMS 系统登录后并点击审批管理的功能后，再使用。或者复制实例 ID 到 OMS 中手动查询 \n\n" +
                mobiles(atMobiles));
        request.setMarkdown(markdown);
        OapiRobotSendRequest.At at = new OapiRobotSendRequest.At();
        at.setAtMobiles(atMobiles);
        at.setIsAtAll(false);
        request.setAt(at);
        sendDingTalk(request);
    }

    public static String mobiles(List<String> atMobiles) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < atMobiles.size(); i++) {
            if (i != 0) {
                sb.append(",");
            }
            sb.append("@").append(atMobiles.get(i));
        }
        return sb.toString();
    }

    public static void sendDingTalkForNodePreCheck(String profile, NextNodePreCheckAlterDTO alterDTO, List<String> alterMobiles) {
        OapiRobotSendRequest request = new OapiRobotSendRequest();
        request.setMsgtype("markdown");
        OapiRobotSendRequest.Markdown markdown = new OapiRobotSendRequest.Markdown();
        markdown.setTitle("Notice 审批模板节点预检查告警, Env: " + profile);
        markdown.setText("#### [" + profile + "]审批模板节点预检查告警\n" +
                "> 审批业务: " + alterDTO.getProcessDefinitionName() + "(" + alterDTO.getProcessDefinitionKey() + ")" + "\n\n" +
                "> 实例 ID：" + alterDTO.getProcessInstanceId() + "\n\n" +
                "> 检测节点 ID：" + alterDTO.getActivityId() + "\n\n" +
                "> ##### 错误信息：" + alterDTO.getErrorMsg() + "\n\n" +
                mobiles(alterMobiles));
        request.setMarkdown(markdown);
        OapiRobotSendRequest.At at = new OapiRobotSendRequest.At();
        at.setAtMobiles(alterMobiles);
        at.setIsAtAll(false);
        request.setAt(at);
        sendDingTalk(request);

    }

    public static void sendDingTalkForTransferToAdminError(String profile, String processInstanceId, String taskDefinitionKey, Object orgScopes, String targetUrl) {
        OapiRobotSendRequest request = new OapiRobotSendRequest();
        request.setMsgtype("markdown");
        OapiRobotSendRequest.Markdown markdown = new OapiRobotSendRequest.Markdown();
        markdown.setTitle("Notice 转交管理员后的审批人为空, Env: " + profile);
        markdown.setText("#### [" + profile + "]转交管理员后的审批人为空\n" +
                "> 流程实例 ID: " + processInstanceId + "\n\n" +
                "> 节点参数(节点 ID): " + taskDefinitionKey + "\n\n" +
                "> OrgScopes 参数信息: " + JSONUtil.toJsonStr(orgScopes) + "\n\n" +
                "> 目标接口: " + targetUrl + "\n\n" +
                "> ##### 提示：仅作为提示信息,不代表是异常");
        request.setMarkdown(markdown);
        sendDingTalk(request);
    }
}
