package com.brframework.commonapppush.service.impl;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.http.Method;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.brframework.commonapppush.domain.UPushConfig;
import com.brframework.commonapppush.entity.PushClientInfo;
import com.brframework.commonapppush.entity.PushLog;
import com.brframework.commonapppush.exception.AppPushException;
import com.brframework.commonapppush.service.AppPushService;
import com.brframework.commonapppush.service.PushClientInfoService;
import com.brframework.commonapppush.service.PushLogService;
import com.brframework.commonapppush.service.UPushConfigService;
import com.brframework.commonapppush.vo.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * APP推送
 * @author xu
 * @date 2019/11/18 19:34
 */
@Service
public class AppPushServiceImpl implements AppPushService {

    @Autowired
    UPushConfigService upushConfigService;

    @Autowired
    PushLogService pushLogService;

    @Autowired
    PushClientInfoService clientInfoService;

    @Override
    public void sendUnicastNotification(String userTokens, String title, String text, String uri, String description) {
        PushClientInfo byUserTokens = clientInfoService.findByUserTokens(userTokens);
        if(byUserTokens == null){
            pushLogService.createUnicastLog(null, null,
                    null, null, title, text, uri, description,
                    PushLog.STATUS_OK, userTokens + "不存在deviceTokens");
            return;
        }
        String deviceTokens = byUserTokens.getDeviceTokens();

        if(deviceTokens.length() == 44){
            sendUnicastNotificationForAndroid(deviceTokens, title, text, uri, description);
        } else if(deviceTokens.length() == 64){
            sendUnicastNotificationForIOS(deviceTokens, title, text, description);
        } else {
            throw new AppPushException("错误的deviceTokens，length = " + description.length());
        }

    }

    @Override
    public void sendBroadcastNotification(String title, String text, String uri, String description) {
        sendBroadcastNotificationForAndroid(title, text, uri, description);
        sendBroadcastNotificationForIOS(title, text, description);
    }

    @Override
    public String sendBroadcastNotificationForAndroid(String title, String text, String uri, String description) {
        UPushConfig config = upushConfigService.get();
        String os = "android";

        UPush appPush = new UPush();
        appPush.setAppKey(getAppKey(os));
        appPush.setTimestamp(System.currentTimeMillis() + "");
        appPush.setType("broadcast");
        appPush.setProductionMode(config.getProductionMode());
        appPush.setDescription(description);

        AndroidPayload payload = new AndroidPayload();
        payload.setDisplayType("notification");
        AndroidPayloadBody payloadBody = new AndroidPayloadBody();
        payloadBody.setTitle(title);
        payloadBody.setText(text);
        if(StringUtils.isNotEmpty(uri)){
            payloadBody.setAfterOpen("go_url");
            payloadBody.setUrl(uri);
        }

        payload.setBody(payloadBody);
        appPush.setPayload(payload);

        String messageId = request(appPush, os);
        pushLogService.createBroadcastLog(messageId,
                "android", title, text, uri, description, PushLog.STATUS_OK, null);
        return messageId;
    }

    @Override
    public String sendBroadcastNotificationForIOS(String title, String text, String description) {
        UPushConfig config = upushConfigService.get();
        String os = "ios";

        UPush appPush = new UPush();
        appPush.setAppKey(getAppKey(os));
        appPush.setTimestamp(System.currentTimeMillis() + "");
        appPush.setType("broadcast");
        appPush.setProductionMode(config.getProductionMode());
        appPush.setDescription(description);

        IOSPayloadAps payloadBody = new IOSPayloadAps();
        IOSPayloadApsAlert alert = new IOSPayloadApsAlert();
        alert.setTitle(title);
        alert.setBody(text);
        payloadBody.setAlert(alert);

        JSONObject paylad = new JSONObject();
        paylad.put("aps", payloadBody);
        appPush.setPayload(paylad);

        String messageId = request(appPush, os);
        pushLogService.createBroadcastLog(messageId,os,
                title, text, null, description, PushLog.STATUS_OK, null);
        return messageId;
    }

    @Override
    public String sendUnicastNotificationForIOS(String deviceTokens, String title, String text, String description) {
        UPushConfig config = upushConfigService.get();
        String os = "ios";

        UPush appPush = new UPush();
        appPush.setAppKey(getAppKey(os));
        appPush.setTimestamp(System.currentTimeMillis() + "");
        appPush.setType("unicast");
        appPush.setProductionMode(config.getProductionMode());
        appPush.setDeviceTokens(deviceTokens);
        appPush.setDescription(description);

        IOSPayloadAps payloadBody = new IOSPayloadAps();
        IOSPayloadApsAlert alert = new IOSPayloadApsAlert();
        alert.setTitle(title);
        alert.setBody(text);
        payloadBody.setAlert(alert);

        JSONObject paylad = new JSONObject();
        paylad.put("aps", payloadBody);
        appPush.setPayload(paylad);

        String messageId = request(appPush, os);

        pushLogService.createUnicastLog(messageId, deviceTokens, clientInfoService.findByDeviceTokens(deviceTokens).getUserTokens(), os,
                title, text, null, description, PushLog.STATUS_OK, null);
        return messageId;
    }

    @Override
    public String sendUnicastNotificationForAndroid(String deviceTokens, String title, String text, String uri, String description) {
        String os = "android";
        UPushConfig config = upushConfigService.get();

        UPush appPush = new UPush();
        appPush.setAppKey(getAppKey(os));
        appPush.setTimestamp(System.currentTimeMillis() + "");
        appPush.setType("unicast");
        appPush.setProductionMode(config.getProductionMode());
        appPush.setDeviceTokens(deviceTokens);
        appPush.setDescription(description);

        AndroidPayload payload = new AndroidPayload();
        payload.setDisplayType("notification");
        AndroidPayloadBody payloadBody = new AndroidPayloadBody();
        payloadBody.setTitle(title);
        payloadBody.setText(text);
        if(StringUtils.isNotEmpty(uri)){
            payloadBody.setAfterOpen("go_url");
            payloadBody.setUrl(uri);
        }


        payload.setBody(payloadBody);
        appPush.setPayload(payload);

        String messageId = request(appPush, os);
        pushLogService.createUnicastLog(messageId, deviceTokens, clientInfoService.findByDeviceTokens(deviceTokens).getUserTokens(), os,
                title, text, uri, description, PushLog.STATUS_OK, null);
        return messageId;
    }

    @Override
    public String request(Object requestBody, String os) {
        Method requestMethod = Method.POST;
        String url = "https://msgapi.umeng.com/api/send";
        String body = JSON.toJSONString(requestBody);
        String appMasterSecret = getAppMasterSecret(os);

        url = url + "?sign=" + umsign(requestMethod, url, body, appMasterSecret);
        JSONObject response = JSON.parseObject(HttpUtil.createRequest(requestMethod, url).body(body).execute().body());
        if("SUCCESS".equals(response.getString("ret"))){
            return response.getJSONObject("data").getString("msg_id");
        } else {
            throw new AppPushException(response.getJSONObject("data").getString("error_code")
                    + ":" + response.getJSONObject("data").getString("error_msg"));
        }
    }

    @Override
    public String umsign(Method requestMethod, String url, String body, String appMasterSecret) {
        return SecureUtil.md5(requestMethod.name().toUpperCase() + url + body + appMasterSecret);
    }

    private String getAppKey(String os){
        UPushConfig config = upushConfigService.get();
        if(os.equals("android")){
            return config.getAndroidAppKey();
        } else {
            return config.getIosAppKey();
        }
    }

    private String getAppMasterSecret(String os){
        UPushConfig config = upushConfigService.get();
        if(os.equals("android")){
            return config.getAndroidAppMasterSecret();
        } else {
            return config.getIosAppMasterSecret();
        }
    }
}
