package com.duowenlvshi.duowenlszp.app.HuaWeiPush;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.text.MessageFormat;
import java.util.List;
import java.util.Map;

/**
 * 华为推送
 *
 * @author wangchun
 * @since 2019/7/10 14:39
 */
@Service
public class HuaWeiPusher {
    public static final Log log = LogFactory.getLog(HuaWeiPusher.class);
    /**
     * 用户在华为开发者联盟申请的appId和appSecret（会员中心->应用管理，点击应用名称的链接）
     */
    @Value("${huaWeiPush.appSecret}")
    private  String appSecret;

    @Value("${huaWeiPush.appId}")
    private  String appId;
    /**
     * 获取认证Token的URL
     */
    @Value("${huaWeiPush.tokenUrl}")
    private  String tokenUrl;

    /**
     * 应用级消息下发API
     */
    @Value("${huaWeiPush.apiUrl}")
    private  String apiUrl;

    /**
     * Push通知栏消息
     */
    public void sendToLawyerNcMsg( Map<String, String> extraFieldMap) throws IOException {
        refreshToken();
        JSONArray deviceTokens = new JSONArray();//目标设备Token
        deviceTokens.add(extraFieldMap.get("pushToken"));
        JSONObject body = new JSONObject();//仅通知栏消息需要设置标题和内容，透传消息key和value为用户自定义
        body.put("title", extraFieldMap.get("Title"));//消息标题
        body.put("content", extraFieldMap.get("Text"));//消息内容体

        JSONObject param = new JSONObject();
        param.put("appPkgName", "com.falvshuo");//定义需要打开的appPkgName

        JSONObject action = new JSONObject();
        action.put("type", 1);//1 自定义行为：行为由参数intent定义
        param.put("intent", MessageFormat.format("intent://com.huawei.push/{0}#Intent;scheme=customscheme;launchFlags=0x10000000;end",
                IntentHelper.intent(extraFieldMap)));
        action.put("param", param);//消息点击动作参数

        JSONObject msg = new JSONObject();
        msg.put("type", 3);//3: 通知栏消息，异步透传消息请根据接口文档设置
        msg.put("action", action);//消息点击动作
        msg.put("body", body);//通知栏消息body内容

        JSONArray customizeArray = new JSONArray();
        for (Map.Entry<String, String> entry : extraFieldMap.entrySet()) {
            JSONObject item = new JSONObject();
            item.put(entry.getKey(), entry.getValue());
            customizeArray.add(item);
        }

        JSONObject ext = new JSONObject();//扩展信息，含BI消息统计，特定展示风格，消息折叠。
        ext.put("customize", customizeArray);
        JSONObject hps = new JSONObject();//华为PUSH消息总结构体
        hps.put("msg", msg);
        hps.put("ext", ext);

        JSONObject payload = new JSONObject();
        payload.put("hps", hps);

        String postBody = MessageFormat.format(
                "access_token={0}&nsp_svc={1}&nsp_ts={2}&device_token_list={3}&payload={4}",
                URLEncoder.encode(Config.accessToken, "UTF-8"),
                URLEncoder.encode("openpush.message.api.send", "UTF-8"),
                URLEncoder.encode(String.valueOf(System.currentTimeMillis() / 1000), "UTF-8"),
                URLEncoder.encode(deviceTokens.toString(), "UTF-8"),
                URLEncoder.encode(payload.toString(), "UTF-8"));
        log.info(postBody);
        log.info(payload);
        String postUrl = apiUrl + "?nsp_ctx=" + URLEncoder.encode("{\"ver\":\"1\", \"appId\":\"" + appId + "\"}", "UTF-8");
        httpPost(postUrl, postBody, 5000, 5000);
    }

    /**
     * Push透传消息
     */
    public void sendToLawyerTransMsg(Map<String, String> extraFieldMap) throws IOException {
        refreshToken();
        JSONArray deviceTokens = new JSONArray();//目标设备Token
        deviceTokens.add(extraFieldMap.get("pushToken"));
        JSONObject body = new JSONObject();
        for (Map.Entry<String, String> entry : extraFieldMap.entrySet()) {
            body.put(entry.getKey(), entry.getValue());//透传消息自定义body内容
        }

        JSONObject msg = new JSONObject();
        msg.put("type", 1);//1: 透传异步消息，通知栏消息请根据接口文档设置
        msg.put("body", body.toString());//body内容不一定是JSON，可以是String，若为JSON需要转化为String发送

        JSONObject hps = new JSONObject();//华为PUSH消息总结构体
        hps.put("msg", msg);

        JSONObject payload = new JSONObject();
        payload.put("hps", hps);

        String postBody = MessageFormat.format(
                "access_token={0}&nsp_svc={1}&nsp_ts={2}&device_token_list={3}&payload={4}",
                URLEncoder.encode(Config.accessToken, "UTF-8"),
                URLEncoder.encode("openpush.message.api.send", "UTF-8"),
                URLEncoder.encode(String.valueOf(System.currentTimeMillis() / 1000), "UTF-8"),
                URLEncoder.encode(deviceTokens.toString(), "UTF-8"),
                URLEncoder.encode(payload.toString(), "UTF-8"));
        String postUrl = apiUrl + "?nsp_ctx=" + URLEncoder.encode("{\"ver\":\"1\", \"appId\":\"" + appId + "\"}", "UTF-8");
        httpPost(postUrl, postBody, 5000, 5000);
    }

    /**
     * 获取下发通知消息的认证Token
     */
    protected  void refreshToken() throws IOException {
        if (Config.tokenExpiredTime > System.currentTimeMillis()) {
            return;
        }
        log.info("--> 获取新的accessToken <--");
        String msgBody = MessageFormat.format(
                "grant_type=client_credentials&client_secret={0}&client_id={1}",
                URLEncoder.encode(appSecret, "UTF-8"), appId);
        String response = httpPost(tokenUrl, msgBody, 5000, 5000);
        JSONObject obj = JSONObject.parseObject(response);
        Config.accessToken = obj.getString("access_token");
        Config.tokenExpiredTime = System.currentTimeMillis() + obj.getLong("expires_in") - 5 * 60 * 1000;
    }

    /**
     * http请求
     *
     * @param httpUrl        请求url
     * @param data           请求数据
     * @param connectTimeout 连接超时时间
     * @param readTimeout    超时时间
     * @return
     * @throws IOException
     */
    protected static String httpPost(String httpUrl, String data, int connectTimeout, int readTimeout) throws IOException {
        OutputStream outPut = null;
        HttpURLConnection urlConnection = null;
        InputStream in = null;

        try {
            URL url = new URL(httpUrl);
            urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setRequestMethod("POST");
            urlConnection.setDoOutput(true);
            urlConnection.setDoInput(true);
            urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
            urlConnection.setConnectTimeout(connectTimeout);
            urlConnection.setReadTimeout(readTimeout);
            urlConnection.connect();

            // POST data
            outPut = urlConnection.getOutputStream();
            outPut.write(data.getBytes("UTF-8"));
            outPut.flush();

            // read response
            if (urlConnection.getResponseCode() < 400) {
                in = urlConnection.getInputStream();
            } else {
                in = urlConnection.getErrorStream();
            }

            List<String> lines = IOUtils.readLines(in, urlConnection.getContentEncoding());
            StringBuffer strBuf = new StringBuffer();
            for (String line : lines) {
                strBuf.append(line);
            }
            log.info(strBuf);
            return strBuf.toString();
        } finally {
            IOUtils.closeQuietly(outPut);
            IOUtils.closeQuietly(in);
            if (urlConnection != null) {
                urlConnection.disconnect();
            }
        }
    }
}
