package com.sjkj.base_lib.net.utils;

import androidx.annotation.NonNull;

import com.orhanobut.logger.Logger;

import java.io.EOFException;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Locale;

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

public class LogInterceptor implements Interceptor {

    private String requestBodyString;
    private String requestUrlString;
    private String responseTimeString;
    private String responseStateString;
    private String responseBodyString;
    public static boolean isShowRequestBody = true;

    @NonNull
    @Override
    public Response intercept(@NonNull Chain chain) throws IOException {
        Response response = null;
        Request request = chain.request();
        response = chain.proceed(request);
        //the request url
        String url = request.url().toString();
        //the request method
        String method = request.method();
        long t1 = System.nanoTime();
        requestUrlString = String.format(Locale.getDefault(), "Request %s request [url = %s]", method, url);

        //the request body
        RequestBody requestBody = request.body();
        if (requestBody != null) {
            StringBuilder sb = new StringBuilder("Request Body [");
            Buffer buffer = new Buffer();
            requestBody.writeTo(buffer);
            Charset charset = StandardCharsets.UTF_8;
            MediaType contentType = requestBody.contentType();
            if (contentType != null) {
                charset = contentType.charset(charset);
                if (isPlaintext(buffer)) {
                    sb.append(buffer.readString(charset));
                    sb.append(" (Content-Type = ").append(contentType.toString()).append(",")
                            .append(requestBody.contentLength()).append("-byte body)");
                } else {
                    sb.append(" (Content-Type = ").append(contentType.toString())
                            .append(",binary ").append(requestBody.contentLength()).append("-byte body omitted)");
                }
            }

            sb.append("]");
            requestBodyString = String.format(Locale.getDefault(), "%s %s", method, sb.toString());
        }
        long t2 = System.nanoTime();
        //the response time
        responseTimeString = String.format(Locale.getDefault(), "Response for [url = %s] in %.1fms", url, (t2 - t1) / 1e6d);

        //the response state
        responseStateString = String.format(Locale.CHINA, "Response is %s ,message[%s],code[%d]", response.isSuccessful() ? "success" : "fail", response.message(), response.code());

        //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 bodyString = buffer.clone().readString(charset);
        responseBodyString = String.format("Response json string [%s]", bodyString);
        if (isShowRequestBody) {
            Logger.d(requestUrlString + "\n" + requestBodyString + "\n" + responseTimeString + "\n" + responseStateString + "\n" + responseBodyString);
        } else {
            Logger.d(requestUrlString + "\n" + responseTimeString + "\n" + responseStateString + "\n" + responseBodyString);
        }

        return response;


    }

    static boolean isPlaintext(Buffer buffer) {
        try {
            Buffer prefix = new Buffer();
            long byteCount = buffer.size() < 64 ? buffer.size() : 64;
            buffer.copyTo(prefix, 0, byteCount);
            for (int i = 0; i < 16; i++) {
                if (prefix.exhausted()) {
                    break;
                }
                int codePoint = prefix.readUtf8CodePoint();
                if (Character.isISOControl(codePoint) && !Character.isWhitespace(codePoint)) {
                    return false;
                }
            }
            return true;
        } catch (EOFException e) {
            return false; // Truncated UTF-8 sequence.
        }
    }
}
