package tech.starwin.utils;

import android.os.Build;
import android.text.TextUtils;
import android.util.Log;


import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import okhttp3.FormBody;
import okhttp3.Request;
import tech.starwin.utils.context_utils.DeviceUtils;
import tech.starwin.utils.format_utils.StringFormat;

/**
 * Created by SiKang on 2019-08-07.
 */
public class RequestHandler {
    private final String TAG = "RequestHandler_LOG";
    public static final String DEVICE_SIGN = "deviceSign";
    public static final String SD_SIGN = "sdSign";
    private Request.Builder requestBuilder;
    private String secretKey;
    private Map<String, String> headers;
    private Map<String, String> params;
    private String random;


    private RequestHandler() {

    }

    private RequestHandler(Request.Builder builder, String secretKey, String random, Map<String, String> headers, Map<String, String> params) {
        //要签名header必须全部不为空才开启校验
        if (headers.containsKey("invalid")) {
            headers.clear();
        }
        this.requestBuilder = builder;
        this.secretKey = secretKey;
        this.headers = headers;
        this.params = params;
        if (!TextUtils.isEmpty(random)) {
            this.random = random;
        } else {
            this.random = UUID.randomUUID().toString();
        }

    }


    /**
     * 生成签名MD5
     */
    public String getHeaderSignature() {
        String paramStr = "";
        if (headers.size() > 0) {
            paramStr += format(headers);
        }
        if (params.size() > 0) {
            paramStr += "&" + format(params);
            paramStr = paramStr.startsWith("&") ? paramStr.replaceFirst("&", "") : paramStr;
        }

        String signature = paramStr + decryptSecretKey(secretKey) + random;
//        Log.d(TAG, "code - " + signature);
//        Log.d(TAG, "sign - " + StringFormat.MD5(signature));
        return StringFormat.MD5(signature);
    }


    /**
     * 使用Builder 直接添加Header
     */
    public void signHeaders() {
        if (requestBuilder != null) {
            try {
                String sign = getHeaderSignature();
                if (headers.get(SD_SIGN) != null && headers.get(DEVICE_SIGN) != null) {
                    requestBuilder.addHeader("X-SD-SIGN", headers.get(SD_SIGN)) //SD卡指纹
                            .addHeader("X-DEVICE-SIGN", headers.get(DEVICE_SIGN)); //设备指纹
                }
                requestBuilder.addHeader("X-SDK-VERSION", String.valueOf(Build.VERSION.SDK_INT)) //Android SDK 版本
                        .addHeader("X-HAEDWARE-INFO", URLEncoder.encode("", "UTF-8")) //硬件信息
                        .addHeader("X-APP-SIGN", sign) // Header 签名
                        .addHeader("X-APP-RANDOM", getRandom());// 随机串
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
    }

    public String getRandom() {
        return random;
    }

    private String format(Map<String, String> params) {
        try {
            StringBuilder sb = new StringBuilder();
            List<String> paramsKey = new ArrayList<>(params.keySet());
            Collections.sort(paramsKey);
            for (String key : paramsKey) {
                sb.append("&" + key + "=" + URLDecoder.decode(params.get(key), "UTF-8"));
            }
            return sb.toString().replaceFirst("&", "");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * app秘钥解密
     *
     * @param secretKey display返回的restUrlSignKey字段
     * @return
     */
    public static String decryptSecretKey(String secretKey) {
        if (TextUtils.isEmpty(secretKey)) {
            return "";
        }
        byte[] decode = Base64.getDecoder().decode(secretKey);
        return new String(ThreeDes.decrypt(decode));
    }


    public static class Builder {
        private String secretKey; //  display返回的restUrlSignKey字段
        private Map<String, String> params;
        private Map<String, String> headers;
        private String random;
        private Request.Builder requestBuilder;

        public Builder(String secretKey) {
            this.secretKey = secretKey;
            headers = new HashMap<>();
            params = new HashMap<>();
        }

        //指定随机串
        public Builder random(String random) {
            this.random = random;
            return this;
        }

        public Builder headerSDSign(String value) {
            addHeader(SD_SIGN, value);
            return this;
        }

        public Builder headerDeviceSign(String value) {
            addHeader(DEVICE_SIGN, value);
            return this;
        }

        private Builder addHeader(String key, String value) {
            //必须所有header都不为空才校验
            if (TextUtils.isEmpty(key) || TextUtils.isEmpty(value)) {
                this.headers.put("invalid", "invalid");
            } else {
                this.headers.put(key, value);
            }
            return this;
        }

        /**
         * 绑定request Builder
         */
        public Builder bindHttpBuilder(Request request, Request.Builder builder) {
            this.requestBuilder = builder;
            HashMap<String, String> paramsMap = null;
            if (request.body() instanceof FormBody) {
                FormBody body = (FormBody) request.body();
                paramsMap = new HashMap<>();
                for (int i = 0; i < body.size(); i++) {
                    paramsMap.put(body.encodedName(i), body.encodedValue(i));
                }
            }
            parameters(request.url().toString(), paramsMap);
            return this;
        }

        public Builder parameter(String key, String value) {
            if (!TextUtils.isEmpty(key) && !TextUtils.isEmpty(value)) {
                this.params.put(key, value);
            }
            return this;
        }

        /**
         * 添加请求参数
         */
        public Builder parameters(String url, Map<String, String> params) {
            if (url.split("\\?").length > 1) {
                String paramsGET = url.split("\\?")[1];
                for (String param : paramsGET.split("&")) {
                    String values[] = param.split("=");
                    if (values.length > 0) {
                        String key = values[0];
                        String value = values.length > 1 ? values[1] : "";
                        this.params.put(key, value);
                    }
                }
            }

            if (params != null && params.size() > 0) {
                this.params.putAll(params);
            }
            return this;
        }

        public RequestHandler build() {
            return new RequestHandler(requestBuilder, secretKey, random, headers, params);
        }

    }


}
