package cn.axzo.msg.center.notices.integration.client.impl;

import cn.hutool.core.net.URLEncoder;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Configuration;

import java.util.Map;

/**
 * 信息中心短信服务组件
 *
 * @author liuqibin@axzo.cn
 * @date 2023-12-11
 */
@Log4j2
@RefreshScope
@Configuration
public class RegulatoryGaoxinClient {

    /**
     * 帐号
     */
    @Value("${regulatory.sms.corpId}")
    private String corpId;

    /**
     * 密码
     */
    @Value("${regulatory.sms.pwd}")
    private String pwd;

    /**
     * 短信签名
     */
    @Value("${regulatory.sms.signName}")
    private String signName;

    /**
     * 平台地址
     */
    @Value("${regulatory.sms.url}")
    private String url;

    /**
     * 直接根据短信内容进行发送
     *
     * @param phone   手机号
     * @param content 短信内容
     */
    public String send(String phone, String content) {
        //参数判断
        if (StrUtil.isBlank(phone) || StrUtil.isBlank(content)) {
            log.warn("必要参数（手机号、内容）信息为空，无法执行短信发送");
            return null;
        }

        //组装请求参数
        String requestParam = this.createParam(
                phone, content, StrUtil.EMPTY_JSON, Boolean.FALSE
        );

        //执行发送
        return this.executeSend(requestParam);
    }

    /**
     * 创建请求参数
     *
     * @param phone   手机号
     * @param content 短信内容（模板）
     * @param params  json参数
     * @return 请求参数
     */
    private String createParam(String phone, String content, String params, Boolean formatContent) {
        //格式化短信内容信息
        if (BooleanUtil.isTrue(formatContent)) {
            content = this.formatContent(content, params);
        }

        //添加签名并进行编码
        String encodeContent = this.addSignAndEncodeContent(content);
        if (StrUtil.isBlank(encodeContent)) {
            log.warn("短信内容信息处理失败，无法进行参数组装操作");
            return StrUtil.EMPTY;
        }

        //组装参数并返回
        Map<String, String> param = Maps.newHashMap();
        param.put("CorpID", corpId);
        param.put("Pwd", pwd);
        param.put("Mobile", phone);
        param.put("Content", encodeContent);
        return HttpUtil.toParams(param);
    }

    /**
     * 执行发送
     *
     * @param param 参数
     */
    private String executeSend(String param) {
        try {
            //构建url
            String requestUrl = this.createUrl(param);

            log.info("发送政务短信请求: {}", requestUrl);

            //执行请求
            String result = HttpUtil.post(
                    requestUrl, StrUtil.EMPTY_JSON
            );

            //打印发送结果
            log.info("短信发送完成，本次执行短信发送的结果为：{}", result);
            return result;
        } catch (Exception e) {
            log.error("执行短信发送出错，错误信息为：", e);
        }
        return null;
    }

    /**
     * 构建请求链接信息
     *
     * @param params 请求参数
     * @return 请求链接
     */
    private String createUrl(String params) {
        return url.concat("?")
                .concat(params);
    }

    /**
     * 格式化短信内容
     *
     * @param template 短信模板
     * @param params   json参数
     * @return 短信内容
     */
    private String formatContent(String template, String params) {
        //转换为json
        JSONObject parsed = JSON.parseObject(params);

        //处理参数
        String paramTag;
        String key;
        Object val;
        for (Map.Entry<String, Object> entry : parsed.entrySet()) {
            key = entry.getKey();
            val = entry.getValue();
            if (StrUtil.isBlank(key) || ObjectUtil.isNull(val)) {
                return StrUtil.EMPTY;
            }
            paramTag = this.createParamTag(key);
            if (StrUtil.isBlank(paramTag)) {
                return StrUtil.EMPTY;
            }
            template = template.replaceAll(paramTag, String.valueOf(val));
        }

        //返回处理结果
        return template;
    }

    /**
     * 给短信内容添加签名并编码
     * <p>
     * 需要对内容使用GBK编码
     * </p>
     *
     * @param content 短信内容
     * @return 添加签名
     */
    private String addSignAndEncodeContent(String content) {
        if (StrUtil.isBlank(content)) {
            return StrUtil.EMPTY;
        }
        return URLEncoder.ALL.encode(
                content.concat(signName), CharsetUtil.CHARSET_GBK
        );
    }

    /**
     * 创建参数标识：${param}
     *
     * @param paramName 参数名称
     * @return 参数标识
     */
    private String createParamTag(String paramName) {
        if (StrUtil.isBlank(paramName)) {
            return StrUtil.EMPTY;
        }
        return StrUtil.BACKSLASH.concat("$")
                .concat(StrUtil.BACKSLASH).concat(StrUtil.DELIM_START)
                .concat(paramName).concat(StrUtil.BACKSLASH)
                .concat(StrUtil.DELIM_END);
    }
}