package cn.pluss.platform.util;

import cn.hutool.crypto.SecureUtil;
import cn.pluss.platform.config.GetuiConfig;
import cn.pluss.platform.exception.MsgException;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.util.*;

/**
 * 个推按照cid推送,
 * <b>没有区分安卓和iOS</b>
 */
@Slf4j
public class GetuiPushUtil implements IPush {

    private static IPush instance;

    public static IPush getInstance() {
        if (instance == null) {
            instance = new GetuiPushUtil();
        }

        return instance;
    }

    private static RestTemplate restTemplate;

    private static RestTemplate getRestTemplate() {
        if (restTemplate == null) {
            restTemplate = new RestTemplate();
            ResponseErrorHandler responseErrorHandler = new ResponseErrorHandler() {
                @Override
                public boolean hasError(ClientHttpResponse response) throws IOException {
                    return false;
                }

                @Override
                public void handleError(ClientHttpResponse response) throws IOException {
                }
            };
            restTemplate.setErrorHandler(responseErrorHandler);
        }

        return restTemplate;
    }

    public void init() {
        // token初始化
        if (GetuiConfig.token == null) {
            initToken();
        }

        // token超时初始化
        if (System.currentTimeMillis() + 1000 > GetuiConfig.expireTime) {
            initToken();
        }
    }

    private static void initToken() {
        String authUrl = "https://restapi.getui.com/v2/lcpLtzlX1IAVVHaMzO7rI9/auth";

        Map<String, Object> map = new HashMap<>();
        long currentTimeMillis = System.currentTimeMillis();
        System.out.println(currentTimeMillis);
        map.put("timestamp", currentTimeMillis);
        map.put("appkey", "qH8axt3RQ97lSPA1nsol1");

        String sign = SecureUtil.sha256("qH8axt3RQ97lSPA1nsol1" + currentTimeMillis + "5QOwOzksge8R0ikThr0Ma1");
        map.put("sign", sign);

        JSONObject resp = getRestTemplate().postForObject(authUrl, map, JSONObject.class);
        if (resp == null) {
            log.error("个推获取授权接口请求异常");
            throw new MsgException("个推获取授权接口请求异常");
        }

        if (resp.getIntValue("code") != 0) {
            log.error("个推获取授权接口请求异常: {}", resp.getString("msg"));
            throw new MsgException(resp.getString("msg"));
        }

        JSONObject data = resp.getJSONObject("data");
        GetuiConfig.token = data.getString("token");
        GetuiConfig.expireTime = data.getLong("expire_time");
    }

    @Override
    public void sendAndroidByAlias(List<String> cidList, String notificationTitle, String msgContent, String extrasParam) {
        init();
        // 创建消息
        HttpHeaders headers = new HttpHeaders();
        headers.add("token", GetuiConfig.token);

        JSONObject param1 = new JSONObject();
        param1.fluentPut("request_id", UUID.randomUUID().toString().replace("-", ""))
                .fluentPut("group_name", UUID.randomUUID().toString().replace("-", ""))
                .fluentPut("settings", new JSONObject().fluentPut("ttl", 3600000));

        JSONObject extra = new JSONObject();
        extra.put("url", extrasParam);
        extra.put("content", msgContent);
        extra.put("title", notificationTitle);

        JSONObject notification1 = new JSONObject();
        notification1.put("title", notificationTitle);
        notification1.put("body", msgContent);
        notification1.put("click_type", "payload");
        notification1.put("payload", extra.toString());
        param1.fluentPut("push_message", new JSONObject().fluentPut("notification", notification1));

        JSONObject pushChannel = new JSONObject();
        JSONObject iosChannel = new JSONObject();
        iosChannel.put("type", "notify");
        iosChannel.put("payload", extra.toString());

        JSONObject aps = new JSONObject();
        aps.put("alert", new JSONObject().fluentPut("title", notificationTitle).fluentPut("body", msgContent));
        aps.put("content-available", 0);
        iosChannel.put("aps", aps);
        iosChannel.put("auto_badge", "+1");
        pushChannel.put("ios", iosChannel);
        param1.put("push_channel", pushChannel);

        HttpEntity<JSONObject> httpEntity = new HttpEntity<>(param1, headers);
        JSONObject resp = getRestTemplate().postForObject(GetuiConfig.createMsg, httpEntity, JSONObject.class);
        if (resp == null) {
            log.error("个推推送接口请求异常");
            // throw new MsgException("个推推送接口请求异常");
            return;
        }
        log.error("resp: {}", resp);

        if (resp.getIntValue("code") != 0) {
            log.error("个推推送接口请求异常: {}", resp.getString("msg"));
            // throw new MsgException(resp.getString("msg"));
            return;
        }

        String taskId = resp.getJSONObject("data").getString("taskid");

        JSONObject param = new JSONObject();
        param.put("is_async", true);
        param.put("audience", new JSONObject().fluentPut("cid", cidList));
        param.put("taskid", taskId);

        HttpEntity<JSONObject> httpEntity2 = new HttpEntity<>(param, headers);
        JSONObject resp2 = getRestTemplate().postForObject(GetuiConfig.listCid, httpEntity2, JSONObject.class);
        if (resp2 == null) {
            log.error("个推推送接口请求异常");
            // throw new MsgException("个推推送接口请求异常");
            return;
        }
        log.error("resp2: {}", resp2);

        if (resp2.getIntValue("code") != 0) {
            log.error("个推推送接口请求异常: {}", resp.getString("msg"));
            // throw new MsgException(resp.getString("msg"));
        }
    }

    @Override
    public void sendIOSByAlias(List<String> cidList, String notificationTitle, String msgContent, String extrasParam) {
        init();

        // 创建消息
        HttpHeaders headers = new HttpHeaders();
        headers.add("token", GetuiConfig.token);

        JSONObject param1 = new JSONObject();
        param1.fluentPut("request_id", UUID.randomUUID().toString().replace("-", ""))
                .fluentPut("group_name", UUID.randomUUID().toString().replace("-", ""))
                .fluentPut("settings", new JSONObject().fluentPut("ttl", 3600000));

        JSONObject notification1 = new JSONObject();
        notification1.put("title", notificationTitle);
        notification1.put("body", msgContent);
        notification1.put("click_type", "payload");
        notification1.put("payload", extrasParam);
        param1.fluentPut("push_message", new JSONObject().fluentPut("notification", notification1));

        HttpEntity<JSONObject> httpEntity = new HttpEntity<>(param1, headers);
        JSONObject resp = getRestTemplate().postForObject(GetuiConfig.createMsg, httpEntity, JSONObject.class);
        if (resp == null) {
            log.error("个推推送接口请求异常");
            // throw new MsgException("个推推送接口请求异常");
            return;
        }
        log.error("resp: {}", resp);

        if (resp.getIntValue("code") != 0) {
            log.error("个推推送接口请求异常: {}", resp.getString("msg"));
            // throw new MsgException(resp.getString("msg"));
            return;
        }

        String taskId = resp.getJSONObject("data").getString("taskid");

        JSONObject param = new JSONObject();
        param.put("is_async", true);
        param.put("audience", new JSONObject().fluentPut("cid", cidList));
        param.put("taskid", taskId);

        HttpEntity<JSONObject> httpEntity2 = new HttpEntity<>(param, headers);
        JSONObject resp2 = getRestTemplate().postForObject(GetuiConfig.listCid, httpEntity2, JSONObject.class);
        if (resp2 == null) {
            log.error("个推推送接口请求异常");
            // throw new MsgException("个推推送接口请求异常");
            return;
        }
        log.error("resp2: {}", resp2);

        if (resp2.getIntValue("code") != 0) {
            log.error("个推推送接口请求异常: {}", resp.getString("msg"));
            // throw new MsgException(resp.getString("msg"));
        }
    }

    @Override
    public void sendAllPlatByAlias(List<String> alias, String notificationTitle, String msgContent, String extrasParam) {
        sendAndroidByAlias(alias, notificationTitle, msgContent, extrasParam);
    }

    @Override
    public void sendIOSAll(String notificationTitle, String msgContent, String extrasParam) {
        init();
        HttpHeaders headers = new HttpHeaders();
        headers.add("token", GetuiConfig.token);

        JSONObject param = new JSONObject();
        param.put("is_async", true);
        param.put("request_id", UUID.randomUUID().toString().replace("-", ""));
        param.put("settings", new JSONObject().fluentPut("ttl", 3600000));

        JSONObject tag = new JSONObject()
                .fluentPut("key", "phone_type")
                .fluentPut("values", new String[]{"android"})
                .fluentPut("opt_type", "and");

        param.put("audience", new JSONArray().fluentAdd(tag));

        JSONObject notification = new JSONObject();
        notification.put("title", notificationTitle);
        notification.put("body", msgContent);
        notification.put("click_type", "payload");
        notification.put("payload", extrasParam);
        param.put("push_message", notification);

        HttpEntity<JSONObject> httpEntity = new HttpEntity<>(param, headers);
        JSONObject resp = getRestTemplate().postForObject(GetuiConfig.all, httpEntity, JSONObject.class);
        if (resp == null) {
            log.error("个推推送接口请求异常");
            // throw new MsgException("个推推送接口请求异常");
            return;
        }

        if (resp.getIntValue("code") != 0) {
            log.error("个推推送接口请求异常: {}", resp.getString("msg"));
            // throw new MsgException(resp.getString("msg"));
        }
    }

    @Override
    public void sendAndroidAll(String notificationTitle, String msgContent, String extrasParam) {
        init();
        HttpHeaders headers = new HttpHeaders();
        headers.add("token", GetuiConfig.token);

        JSONObject param = new JSONObject();
        param.put("is_async", true);
        param.put("request_id", UUID.randomUUID().toString().replace("-", ""));
        param.put("settings", new JSONObject().fluentPut("ttl", 3600000));

        JSONObject tag = new JSONObject()
                .fluentPut("key", "phone_type")
                .fluentPut("values", new String[]{"ios"})
                .fluentPut("opt_type", "and");

        param.put("audience", new JSONArray().fluentAdd(tag));

        JSONObject notification = new JSONObject();
        notification.put("title", notificationTitle);
        notification.put("body", msgContent);
        notification.put("click_type", "payload");
        notification.put("payload", extrasParam);
        param.put("push_message", notification);

        HttpEntity<JSONObject> httpEntity = new HttpEntity<>(param, headers);
        JSONObject resp = getRestTemplate().postForObject(GetuiConfig.all, httpEntity, JSONObject.class);
        if (resp == null) {
            log.error("个推推送接口请求异常");
            // throw new MsgException("个推推送接口请求异常");
            return;
        }

        if (resp.getIntValue("code") != 0) {
            log.error("个推推送接口请求异常: {}", resp.getString("msg"));
            // throw new MsgException(resp.getString("msg"));
        }
    }

    @Override
    public void sendAllPlatAll(String notificationTitle, String msgContent, String extrasParam) {
        init();
        HttpHeaders headers = new HttpHeaders();
        headers.add("token", GetuiConfig.token);

        JSONObject param = new JSONObject();
        param.put("is_async", true);
        param.put("request_id", UUID.randomUUID().toString().replace("-", ""));
        param.put("settings", new JSONObject().fluentPut("ttl", 3600000));
        param.put("audience", "all");

        JSONObject notification = new JSONObject();
        notification.put("title", notificationTitle);
        notification.put("body", msgContent);
        notification.put("click_type", "payload");
        notification.put("payload", extrasParam);
        param.put("push_message", notification);


        HttpEntity<JSONObject> httpEntity = new HttpEntity<>(param, headers);
        JSONObject resp = getRestTemplate().postForObject(GetuiConfig.all, httpEntity, JSONObject.class);
        if (resp == null) {
            log.error("个推推送接口请求异常");
            throw new MsgException("个推推送接口请求异常");
        }

        if (resp.getIntValue("code") != 0) {
            log.error("个推推送接口请求异常: {}", resp.getString("msg"));
            throw new MsgException(resp.getString("msg"));
        }
    }
}
