package com.liquidnet.common.sms.processor;

import com.alibaba.fastjson.JSON;
import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.*;
import com.aliyun.teaopenapi.models.Config;
import com.liquidnet.commons.lang.util.CurrentUtil;
import com.liquidnet.commons.lang.util.ServletUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;

@Slf4j
@Component
public class SmsProcessor {
    /* ================================================================== | aliyun dysms */
    @Value("${liquidnet.aliyun.dysms.accessKeyId}")
    private String aliyunDysmsAccessKeyId;
    @Value("${liquidnet.aliyun.dysms.accessKeySecret}")
    private String aliyunDysmsAccessKeySecret;
    private static Client aliyunDysmsAcsClient;
    /* ================================================================== |  */

    @PostConstruct
    private void init() throws Exception {
        Config config = new Config()
                .setAccessKeyId(aliyunDysmsAccessKeyId)
                .setAccessKeySecret(aliyunDysmsAccessKeySecret)
                .setEndpoint("dysmsapi.aliyuncs.com");
        aliyunDysmsAcsClient = new Client(config);
    }

    /* ================================================================== | aliyun dysms */

    /**
     * AliyunDysms.send
     * - link: https://help.aliyun.com/document_detail/101414.htm?spm=a2c4g.11186623.2.8.302f56958lnARh#t83759.html
     *
     * @param phoneNumber   接收短信的手机号码(国内短信:+/+86/0086/86或无任何前缀的11位手机号码;国际/港澳台消息:国际区号+号码)
     * @param signName      短信签名名称
     * @param templateCode  短信模板ID
     * @param templateParam 短信模板变量对应的实际值，JSON格式(建议使用com.liquidnet.commons.lang.util.JsonUtils.OM().createObjectNode())
     * @return SendSmsResponse
     */
    private SendSmsResponse aliyunDysmsSend(String phoneNumber, String signName, String templateCode, String templateParam) throws Exception {
        SendSmsRequest smsRequest = new SendSmsRequest()
                .setPhoneNumbers(phoneNumber)
                .setSignName(signName)
                .setTemplateCode(templateCode)
                .setTemplateParam(templateParam);
            return aliyunDysmsAcsClient.sendSms(smsRequest);
    }

    /**
     * AliyunDysms.sendBatch
     * - note: 在一次请求中，最多可以向100个手机号码分别发送短信(整体请求量限定在128k以内)
     * - link: https://help.aliyun.com/document_detail/102364.html?spm=a2c4g.11186623.6.633.3d855ecb5j4CR8
     *
     * @param phoneNumberJson   接收短信的手机号码(国内短信:+/+86/0086/86或无任何前缀的11位手机号码;国际/港澳台消息:国际区号+号码)，JSON数组格式(建议使用com.liquidnet.commons.lang.util.JsonUtils.OM().createArrayNode())
     * @param signNameJson      短信签名名称，JSON数组格式(建议使用com.liquidnet.commons.lang.util.JsonUtils.OM().createArrayNode())
     * @param templateCode      短信模板CODE
     * @param templateParamJson 短信模板变量对应的实际值，JSON格式(建议使用com.liquidnet.commons.lang.util.JsonUtils.OM().createObjectNode())
     * @return SendBatchSmsResponse
     */
    private SendBatchSmsResponse aliyunDysmsSendBatch(String phoneNumberJson, String signNameJson, String templateCode, String templateParamJson) throws Exception {
        SendBatchSmsRequest batchSmsRequest = new SendBatchSmsRequest()
                .setPhoneNumberJson(phoneNumberJson)
                .setSignNameJson(signNameJson)
                .setTemplateCode(templateCode)
                .setTemplateParamJson(templateParamJson);
        return aliyunDysmsAcsClient.sendBatchSms(batchSmsRequest);
    }

    /* ================================================================== | sender */

    public boolean send(String phoneNumber, String signName, String templateCode, String templateParam) {
        try {
            SendSmsResponse smsResponse = this.aliyunDysmsSend(phoneNumber, signName, templateCode, templateParam);

            SendSmsResponseBody smsResponseBody = smsResponse.getBody();

            boolean isSucc = null != smsResponseBody && "OK".equalsIgnoreCase(smsResponseBody.getCode());

            if (!isSucc) {
                log.warn("###发送短信API处理失败[pn={},sn={},tc={},tp={},respBody={}]", phoneNumber, signName, templateCode, templateParam, JSON.toJSON(smsResponseBody));
                String cliIpAddr = CurrentUtil.getCliIpAddr();
                log.info("[send] cliIpAddr: {}", cliIpAddr);

                StringBuilder sb = new StringBuilder();
                HttpServletRequest request = ServletUtils.getRequest();
                Enumeration<String> headerNames = request.getHeaderNames();
                while (headerNames.hasMoreElements()) {
                    String headerName = headerNames.nextElement();
                    String headerValue = request.getHeader(headerName);
                    sb.append(headerName).append(": ").append(headerValue).append("\n");
                }
                log.info("[send] headers: {}.", sb);
            }

            return isSucc;
        } catch (Exception e) {
            log.error("发送短信API处理异常[pn={},sn={},tc={},tp={}]", phoneNumber, signName, templateCode, templateParam, e);
        }
        return false;
    }

    /* ================================================================== |  */
}
