package com.pcloud.book.advertising.check;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.pcloud.common.exceptions.BizException;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.util.Base64;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashMap;

@Slf4j
public class QiLiShuSheApiHandler {

    private String appId;

    private String appSecret;

    private String domain;

    public QiLiShuSheApiHandler(String appId, String appSecret, String domain) {
        this.appId = appId;
        this.appSecret = appSecret;
        this.domain = domain;
    }

    public ApiRequestResult post(String path, HashMap<String, Object> bodyMap) {
        HttpRequest post = HttpUtil.createPost(this.domain + path);
        String nonceStr = IdUtil.fastSimpleUUID();
        long timestamp = System.currentTimeMillis() / 1000;
        String body = JSONObject.toJSONString(bodyMap);
        post.header("appid", this.appId);
        post.header("nonceStr", nonceStr);
        post.header("timestamp", String.valueOf(timestamp));
        post.header("signature", getSign("POST", path, sortBody(bodyMap), nonceStr, timestamp));
        post.body(body);
        String result = post.execute().body();

        // 返回值
        ApiRequestResult requestResult = new ApiRequestResult();
        requestResult.setRunSuccess(false);
        requestResult.setApiUrl(post.getUrl());
        requestResult.setApiBody(body);
        requestResult.setApiResult(result);

        log.info("【起礼科技】请求第三方接口结果；result：{}；post：{}", result, post);
        if (StrUtil.isBlank(result)) {
            return requestResult;
        }
        JSONObject jsonObject = JSONObject.parseObject(result);
        if (jsonObject.getBoolean("success")) {
            log.info("【起礼科技】数据同步成功；body：{}", body);
            requestResult.setRunSuccess(true);
            return requestResult;
        }
        log.info("【起礼科技】数据同步失败；body：{}", body);
        return requestResult;
    }

    private String sortBody(HashMap<String, Object> bodyMap) {
        char[] charArray = JSONObject.toJSONString(bodyMap).toCharArray();
        Arrays.sort(charArray);
        return new String(charArray);
    }

    String getSign(String method, String path, String body, String nonceStr, long timestamp) {
        String message = buildMessage(method, path, timestamp, nonceStr, body);
        return sign(message);
    }

    String buildMessage(String method, String path, long timestamp, String nonceStr, String body) {
        return method + "\n"
                + path + "\n"
                + timestamp + "\n"
                + nonceStr + "\n"
                + body + "\n";
    }

    String sign(String stringToSign) {
        try {
            Mac hmacSha256 = Mac.getInstance("HmacSHA256");
            byte[] keyBytes = this.appSecret.getBytes(StandardCharsets.UTF_8); //appkey 为绑定到API 上的签名密钥
            hmacSha256.init(new SecretKeySpec(keyBytes, 0, keyBytes.length, "HmacSHA256"));
            return new String(Base64.encodeBase64(hmacSha256.doFinal(stringToSign.getBytes("UTF-8"))), "UTF-8");
        } catch (Exception e) {
            throw new BizException(BizException.DB_DML_FAIL.getCode(), "【起礼科技】第三方签名生成失败；");
        }
    }

    @Data
    public static class ApiRequestResult implements Serializable {

        private Boolean runSuccess;

        private String apiUrl;

        private String apiBody;

        private String apiResult;

    }
}
