package com.duben.microtribe.net;

import android.text.TextUtils;

import com.bytedance.hume.readapk.HumeSDK;
import com.google.gson.Gson;
import com.duben.microtribe.BuildConfig;
import com.duben.microtribe.utils.MateUtils;
import com.duben.microtribe.utils.rxutil.CommonUtils;
import com.duben.library.utils.ConstantUtil;
import com.duben.microtribe.MintsApplication;
import com.duben.microtribe.common.Constant;
import com.duben.microtribe.common.DeviceInfo;
import com.duben.microtribe.manager.UserManager;
import com.duben.microtribe.mvp.model.AppRequest;
import com.duben.microtribe.utils.AESUtils;
import com.duben.microtribe.utils.Base64;
import com.duben.microtribe.utils.LogUtil;
import com.duben.microtribe.utils.MD5;
import com.duben.microtribe.utils.StringUtil;

import org.json.JSONObject;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;

import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSource;

/**
 * 用拦截器对传输数据加密
 * Response返回值拦截
 */
public class OkHttpInterceptor implements Interceptor {

    private String aesKey = "";

    /**
     * 实例化拦截器对象
     */
    public OkHttpInterceptor(String aesKey) {
        this.aesKey = aesKey;
    }

    @Override
    public Response intercept(Chain chain) throws IOException {
        String tokenID = UserManager.getInstance().getTokenID();
        long time = System.currentTimeMillis();
        String channel = createChannel();

        Request request = chain.request();
        // 加密
        request = encrypt(request, tokenID, time, channel);
        // header
        Request builder = addHeader(request, tokenID, time, channel);
        // 解密
        Response response = chain.proceed(builder);
        response = decrypt(response);
        return response;
    }

    /**
     * 创建渠道
     *
     * @return
     */
    private String createChannel() {
        String channel = MateUtils.INSTANCE.getAppMetaData(MintsApplication.getContext(), "CHANNEL_NAME");
        try {
            // 穿山甲分包渠道
            String ttChannel = HumeSDK.getChannel(MintsApplication.getContext());
            if (!TextUtils.isEmpty(ttChannel)) {
                // 此处方式不能修改，已和后端约定
                channel = channel + "_" + ttChannel;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return channel;
    }

    /**
     * 添加header
     *
     * @param request
     * @param tokenID
     * @param time
     * @param channel
     * @return
     */
    private Request addHeader(Request request, String tokenID, long time, String channel) throws UnsupportedEncodingException {
        return request.newBuilder().
                addHeader("version", DeviceInfo.Companion.getInstance().getVersionName()).
                addHeader("token", tokenID).
                addHeader("pkgName", Constant.MINTS_PKG_NAME).
                addHeader("channel", channel).
                addHeader("new-session", MD5.GetMD5Code(String.valueOf(time))).
                addHeader("last-session", Base64.encode(String.valueOf(time).getBytes("UTF-8"))).
                build();
    }

    /**
     * json加密
     *
     * @param request
     * @param tokenID
     * @param time
     * @param channel
     * @return
     * @throws IOException
     */
    private Request encrypt(Request request, String tokenID, long time, String channel) throws IOException {
        //获取请求body，只有@Body 参数的requestBody 才不会为 null
        RequestBody requestBody = request.body();
        if (requestBody != null) {
            Buffer buffer = new Buffer();
            requestBody.writeTo(buffer);
            Charset charset = Charset.forName("UTF-8");
            MediaType contentType = requestBody.contentType();
            if (contentType != null) {
                charset = contentType.charset(charset);
            }

            // 原始报文
            String valueStr = buffer.readString(charset);
            String checkStr = valueStr;

            //加密
            if (isSign(request) && !TextUtils.isEmpty(valueStr)) {
                valueStr = AESUtils.encrypt(valueStr, aesKey);
            }

            // 渠道
            String channelName = "android_" + channel;

            // sign
            String requestSign = tokenID + ":" + channelName + ":" + time;
            String sign = MD5.GetMD5Code(requestSign);
            // 验证
            String check = MD5.GetMD5Code(requestSign + ":" + checkStr);

            AppRequest appRequest = new AppRequest();
            appRequest.setChannel(channelName);
            appRequest.setSign(sign);
            appRequest.setCheck(check);
            appRequest.setData(valueStr);

            RequestBody body = MultipartBody.create(contentType, new Gson().toJson(appRequest));
            request = request.newBuilder()
                    .post(body)
                    .build();
        }
        return request;
    }


    /**
     * json解密
     *
     * @param response
     * @return
     * @throws IOException
     */
    private Response decrypt(Response response) throws IOException {
        if (response.isSuccessful() && isSign(response.request())) {
            //the response data
            ResponseBody body = response.body();
            BufferedSource source = body.source();
            source.request(Long.MAX_VALUE); // Buffer the entire body.
            Buffer buffer = source.buffer();
            Charset charset = Charset.defaultCharset();
            MediaType contentType = body.contentType();
            if (contentType != null) {
                charset = contentType.charset(charset);
            }
            String rspString = buffer.clone().readString(charset);
            // 解密
            try {
                JSONObject json = new JSONObject(rspString);
                if (!json.isNull("data")) {
                    Object data = json.get("data");
                    rspString = AESUtils.detrypt(data.toString(), aesKey);
                    JSONObject jsonArray = new JSONObject(rspString);
                    json.put("data", jsonArray);
                    rspString = json.toString();
//                    rspString = json.toString().replace("\\", "");
                }
            } catch (Exception e) {
                LogUtil.d("OkHttpInterceptor", "json解密失败。url：" + response.request().url().toString() + "\n\n  响应报文：" + buffer.clone().readString(charset));
//                TrackManager.getInstance().reportErrornterface(response.request().url().toString(), buffer.clone().readString(charset));
                e.printStackTrace();
            }
            ResponseBody responseBody = ResponseBody.create(contentType, rspString);
            response = response.newBuilder().body(responseBody).build();
        }
        return response;
    }

    /**
     * 是否加/解密 - 接口非common都加/解密
     *
     * @param request
     * @return true=加/解密
     */
    private boolean isSign(Request request) {
//        String url = request.url().toString();
//        //是否加密标识
//        boolean isSign = true;
//        if (!TextUtils.isEmpty(url)) {
//            isSign = !url.contains("common/");
//        }
//        return isSign;
        return true;
    }
}

