package org.tio.sitexxx.service.service.jpush.honor.messaging;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.tio.sitexxx.service.service.jpush.honor.exception.HonorMesssagingException;
import org.tio.sitexxx.service.service.jpush.honor.message.Message;
import org.tio.sitexxx.service.service.jpush.honor.response.SendResponse;
import org.tio.sitexxx.service.service.jpush.huawei.util.ValidatorUtils;
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;

/**
 * <pre>
 *    @author : vagrancy
 *    e-mail : 18050829067@163.com
 *    time   : 2025-02-21 10:55
 *    desc   :
 * </pre>
 */
public class HonorMessageClientImpl implements HonorMessageClient {
    private static final String PUSH_URL = "https://push-api.cloud.honor.com";

    private final String HcmPushUrl;
    private final CloseableHttpClient httpClient;

    private HonorMessageClientImpl(Builder builder) {
        this.HcmPushUrl = MessageFormat.format(PUSH_URL + "/api/v1/{0}/sendMessage", builder.appId);

        ValidatorUtils.checkArgument(builder.httpClient != null, "requestFactory must not be null");
        this.httpClient = builder.httpClient;
    }

    public CloseableHttpClient getHttpClient() {
        return httpClient;
    }

    @Override
    public SendResponse send(Message message, String accessToken) throws HonorMesssagingException {
        try {
            return sendRequest(message, accessToken);
        } catch (IOException e) {
            throw new HonorMesssagingException(HonorMessaging.INTERNAL_ERROR, "Error while calling HCM backend service", e);
        }
    }

    /**
     * send request
     *
     * @param message     message {@link Message}
     * @param accessToken  A String for oauth
     * @return {@link SendResponse}
     * @throws IOException If a error occurs when sending request
     */
    private SendResponse sendRequest(Message message, String accessToken) throws IOException, HonorMesssagingException {
        Map<String, Object> map = createRequestMap(message);
        HttpPost httpPost = new HttpPost(this.HcmPushUrl);
        StringEntity entity = new StringEntity(JSON.toJSONString(map), "UTF-8");
//        String aqa = JSON.toJSONString(map);
        httpPost.setHeader("Authorization", "Bearer " + accessToken);
        httpPost.setHeader("timestamp", String.valueOf(System.currentTimeMillis()));
        httpPost.setHeader("Content-Type", "application/json;charset=utf-8");
        httpPost.setEntity(entity);
        CloseableHttpResponse response = httpClient.execute(httpPost);
        String rpsContent = EntityUtils.toString(response.getEntity());
        int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode == 200) {
            JSONObject jsonObject = JSONObject.parseObject(rpsContent);
            Integer code = jsonObject.getInteger("code");
            String msg = jsonObject.getString("msg");
            Object requestId = jsonObject.getOrDefault("data", "");
            if (code == 200) {
                return SendResponse.fromCode(code, msg, requestId);
            } else {
                String errorMsg = MessageFormat.format("error code : {0}, error message : {1}", String.valueOf(code), msg);
                throw new HonorMesssagingException(HonorMessaging.KNOWN_ERROR, errorMsg);
            }
        }
        HttpResponseException exception = new HttpResponseException(statusCode, rpsContent);
        throw createExceptionFromResponse(exception);
    }

    /**
     * create the map of the request body, mostly for wrapping the message with validate_only
     *
     * @param message      A non-null {@link Message} to be sent.
     * @return a map of request
     */
    private Map<String, Object> createRequestMap(Message message) {
        return new HashMap<String, Object>() {
            {
                put("android", message.getAndroidConfig());
                put("token", message.getToken());
                put("notification", message.getNotification());
            }
        };
    }

    private HonorMesssagingException createExceptionFromResponse(HttpResponseException e) {
        String msg = MessageFormat.format("Unexpected HTTP response with status : {0}, body : {1}", e.getStatusCode(), e.getMessage());
        return new HonorMesssagingException(HonorMessaging.UNKNOWN_ERROR, msg, e);
    }

    static HonorMessageClientImpl fromApp(HonorApp app) {
        String appId = ImplHonorTrampolines.getAppId(app);
        return HonorMessageClientImpl.builder()
                .setAppId(appId)
                .setHttpClient(app.getOption().getHttpClient())
                .build();
    }

    static Builder builder() {
        return new Builder();
    }

    static final class Builder {

        private String appId;
        private CloseableHttpClient httpClient;

        private Builder() {
        }

        public Builder setAppId(String appId) {
            this.appId = appId;
            return this;
        }

        public Builder setHttpClient(CloseableHttpClient httpClient) {
            this.httpClient = httpClient;
            return this;
        }

        public HonorMessageClientImpl build() {
            return new HonorMessageClientImpl(this);
        }
    }

}
