package com.yidianling.ydlcommon.custom.http;

import android.content.Context;
import android.util.Log;
import com.facebook.stetho.okhttp3.StethoInterceptor;
import com.google.gson.JsonParseException;
import com.yidianling.ydlcommon.core.base.BaseApplication;
import com.yidianling.common.tools.LogUtil;
import com.yidianling.common.tools.RxAppTool;
import com.yidianling.common.tools.RxDeviceTool;
import com.yidianling.common.tools.ToastUtil;
import com.yidianling.ydlcommon.BuildConfig;
import com.yidianling.ydlcommon.R;
import com.yidianling.ydlcommon.custom.data.YdlDataManager;
import com.yidianling.ydlcommon.custom.router.YdlCommonRouterManager;
import com.yidianling.ydlcommon.custom.router.YdlUserInfo;
import okhttp3.*;
import okhttp3.logging.HttpLoggingInterceptor;
import okio.Buffer;
import retrofit2.HttpException;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

import javax.net.ssl.SSLSocketFactory;
import java.io.File;
import java.lang.reflect.Field;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.security.MessageDigest;
import java.util.*;
import java.util.concurrent.TimeUnit;


/**
 * 网络请求
 * 根据不同请求返回不同的Call
 */
public class YdlRetrofitUtils {

    public static String YDL_H5 = BuildConfig.YDL_H5_URL;

    public static String POST = BuildConfig.SERVER_URL;
    public static String BASE_JAVA_URL = BuildConfig.SERVER_JAVA_URL;
    public static String H5_URL = BuildConfig.H5_URL;
    public static String MH5_URL = BuildConfig.MH5_URL;
    public static String WEB_URL = BuildConfig.WEB_URL;
    public static String SERVER_COUPON_URL = BuildConfig.SERVER_COUPON_JAVA_URL;
    public static String SERVER_TEMP_JAVA_URL = BuildConfig.SERVER_TEMP_JAVA_URL;
    public static String SERVER_API_JAVA_URL = BuildConfig.SERVER_JAVA_API_URL;
    public static String ACTION_URL = BuildConfig.ACTION_URL;

    private static final int DEFAULT_TIMEOUT = 15;
    private static final String AUTHORIZATION_NAME = "Authorization";
    private static final String SESSION_KEY_DEFAULT_VALUE = "dc59cf294f37d237c1f06240568ffe21";
    private static Retrofit retrofit;
    public static final String M_BASE_URL = "http://m.ydl.com/";//m站的baseUrl

    private static final String UID = "uid";
    private static final String FFROM = "ffrom";
    private static final String IS_FROM_APP = "isFromApp";
    private static final String OS_BUILD = "osBuild";
    private static final String TS = "ts";
    private static final String VERSION = "version";
    private static final String TOKEN = "accessToken";
    private static final String OS_TYPE = "osType";// 1.ios 2.android
    private static final String APP_NAME = "appName";//用于标识 是哪个应用 yidianling:用户版 xinlizixun：心理咨询 haoshi：情感壹点灵 zhuanjia：专家版


    public static void handleError(Context context, Throwable t) {
        t.printStackTrace();
        if (t instanceof SocketTimeoutException || t instanceof UnknownHostException || t instanceof HttpException) {
            if (context != null) {
                ToastUtil.toastShort(context.getString(R.string.network_error));
            }
        } else if (t instanceof JsonParseException) {
            if (context != null) {
                ToastUtil.toastShort(context.getString(R.string.gson_parse_error));
            }
        } else {
//            ToastUtil.toastShort(context, t.getMessage());
            LogUtil.e(t.toString());
        }
    }

    //根据不同的请求获取不同的请求头(RxJava)
    public static Retrofit getRxRetrofit() {
        if (retrofit == null) {
            retrofit = new Retrofit.Builder()
                    .baseUrl(POST)
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .addConverterFactory(GsonConverterFactory.create())
                    .client(getOkHttp())
                    .build();
        }
        return retrofit;
    }

    /**
     * 销毁时调用
     */
    public static void clearRxRetrofit() {
        retrofit = null;
    }


    //获取网络请求表
    public static Map<String, String> getMaps(BaseCommand cmd) {
        Map<String, String> map = new HashMap<>();
        List<FormatText> list = getPostList(cmd);
        int size = list.size();
        for (int i = 0; i < size; i++) {
            FormatText formatText = list.get(i);
            map.put(formatText.getmKey(), String.valueOf(formatText.getmValue()));
        }
        return map;
    }

    //获取文件传输网络请求表
    @SuppressWarnings("unused")
    public static Map<String, RequestBody> getFileMaps(BaseCommand cmd, String key, File[] files) {
        Map<String, RequestBody> map = new TreeMap<>();
        List<FormatText> list = getPostList(cmd);
        int size = list.size();
        for (int i = 0; i < size; i++) {
            FormatText formatText = list.get(i);
//            RequestBody rb = RequestBody.create(MediaType.parse("multipart/form-data"),list.get(i).getmValue());
            RequestBody rb = RequestBody.create(MediaType.parse("text/plain"), String.valueOf(list.get(i).getmValue()));
            map.put(formatText.getmKey(), rb);
        }

        if (files != null && files.length > 0) {
            if (files.length == 1) {
                if (files[0] != null) {
                    RequestBody fileBody = RequestBody.create(MediaType.parse("multipart/form-data"), files[0]);
                    map.put(key + "\"; filename=\"" + files[0].getName() + "", fileBody);
                }
            } else {
                for (int i = 0; i < files.length; i++) {
                    if (files[i] != null) {
                        RequestBody fileBody = RequestBody.create(MediaType.parse("multipart/form-data"), files[i]);
                        map.put(key + i + "\"; filename=\"" + files[i].getName() + "", fileBody);
                    }
                }
            }

        }
        return map;
    }


    //获取网络请求表
    private static Map<String, RequestBody> getFileMaps(List<FormatText> list, String key, File[] file) {
        Map<String, RequestBody> map = new TreeMap<>();
        int size = list.size();
        for (int i = 0; i < size; i++) {
            FormatText formatText = list.get(i);
//            RequestBody rb = RequestBody.create(MediaType.parse("multipart/form-data"),list.get(i).getmValue());
            RequestBody rb = RequestBody.create(MediaType.parse("text/plain"), String.valueOf(list.get(i).getmValue()));
            map.put(formatText.getmKey(), rb);
        }

        if (file != null && file.length > 0) {
            if (file.length == 1) {
                if (file[0] != null) {
                    RequestBody fileBody = RequestBody.create(MediaType.parse("multipart/form-data"), file[0]);
                    map.put(key + "\"; filename=\"" + file[0].getName() + "", fileBody);
                }
            } else {
                for (int i = 0; i < file.length; i++) {
                    if (file[i] != null) {
                        RequestBody fileBody = RequestBody.create(MediaType.parse("multipart/form-data"), file[i]);
                        map.put(key + i + "\"; filename=\"" + file[i].getName() + "", fileBody);
                    }
                }
            }

        }
        return map;
    }


    //获取网络请求表
    public static Map<String, String> getMaps(List<FormatText> list) {
        Map<String, String> map = new HashMap<>();
        int size = list.size();
        for (int i = 0; i < size; i++) {
            FormatText formatText = list.get(i);
            map.put(formatText.getmKey(), String.valueOf(formatText.getmValue()));
        }
        return map;
    }

    /**
     * 用于MD5加密
     *
     * @param clear 明文
     * @return 密文
     */
    private static String digestMD5(String clear) {
        char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                'a', 'b', 'c', 'd', 'e', 'f'};
        try {
            byte[] strTemp = clear.getBytes("utf-8");
            // 使用MD5创建MessageDigest对象
            MessageDigest mdTemp = MessageDigest.getInstance("MD5");
            mdTemp.update(strTemp);
            byte[] md = mdTemp.digest();
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (byte b : md) {
                // 将每个数(int)b进行双字节加密
                str[k++] = hexDigits[b >> 4 & 0xf];
                str[k++] = hexDigits[b & 0xf];
            }
            return new String(str);
        } catch (Exception e) {
            return null;
        }
    }


    private static OkHttpClient getOkHttp() {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.retryOnConnectionFailure(false);
        try {
            builder.addInterceptor(new PostCacheInterceptor(new DiskLruCacheHelper(BaseApplication.Companion.getApp())));
        } catch (Exception e) {
        }
        builder.addInterceptor(chain -> {
            RequestBody body = chain.request().body();
            List<FormatText> list = new ArrayList<>();
            if (body instanceof FormBody) {
                FormBody formBody = (FormBody) body;
                for (int i = 0; i < formBody.size(); i++) {
                    list.add(new FormatText(formBody.name(i), formBody.value(i)));
                }

            }
            if (body instanceof MultipartBody) {
                MultipartBody multipartBody = (MultipartBody) body;
                List<MultipartBody.Part> parts = multipartBody.parts();
                for (MultipartBody.Part part : parts) {
                    //noinspection ConstantConditions
                    if ("text/plain; charset=utf-8".equals(part.body().contentType().toString())) {
                        //noinspection ConstantConditions
                        String headerStr = part.headers().toString();
                        String name = headerStr.split("\"\\n")[0].split("=\"")[1];
                        Log.e("Tag","header="+headerStr+"--name="+name);
                        Buffer buffer = new Buffer();
                        part.body().writeTo(buffer);
                        String value = buffer.readUtf8();
                        list.add(new FormatText(name, value));
                    }
                }
            }
            String head = "Ydl " + getSign(list);
            LogUtil.i("RetrofitLog", "head = " + head);

            Request.Builder build = chain.request()
                    .newBuilder()
                    .header(AUTHORIZATION_NAME, head)
                    .addHeader("Connection","close")
                    .addHeader(FFROM, YdlDataManager.INSTANCE.getRam().getChannelName())
                    .addHeader(IS_FROM_APP, "1")
                    .addHeader(VERSION, RxDeviceTool.getAppVersionName(BaseApplication.Companion.getApp()))
                    .addHeader(OS_BUILD, RxDeviceTool.getBuildMANUFACTURER() + "," + RxDeviceTool.getBuildBrandModel() + "," + RxDeviceTool.getOsBuileVersion() + "," + RxDeviceTool.getAppVersionName(BaseApplication.Companion.getApp()))
                    .addHeader(OS_TYPE,"2")
                    .addHeader(APP_NAME,"yidianling");
            YdlUserInfo loginBean = YdlCommonRouterManager.INSTANCE.getYdlCommonRoute().getUserInfo();
            if (loginBean != null) {
                build.addHeader(TOKEN, loginBean.getToken())
                        .addHeader(UID, loginBean.getUserId());
            }
            return chain.proceed(build.build());
        });

        if (BuildConfig.DEBUG) {
            builder.addInterceptor(new HttpLoggingInterceptor(message -> {
                //打印retrofit日志
                LogUtil.i("RetrofitLog", "retrofitBack = " + message);
            }).setLevel(HttpLoggingInterceptor.Level.BODY));
            builder.addNetworkInterceptor(new StethoInterceptor());
        }
        //使用自定义SSLSocketFactory
        SSLSocketFactory factory = YDLSSLFactory.getSocketFactory();
        if (factory != null) {
            //noinspection deprecation
            builder.sslSocketFactory(factory)
                    .hostnameVerifier((hostname, session) -> true
                    );
        }
        builder.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
                .readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
                .writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
        return builder.build();
    }


    //获取请求头签名
    private static String getSign(List<FormatText> list) {
        //将请求参数倒序排列
        Collections.sort(list, new SortData());
        StringBuilder stringBuilder = new StringBuilder();
        int size = list.size();
        for (int i = 0; i < size; i++) {
            FormatText formatText = list.get(i);
            if (i != 0) {
                stringBuilder.append("&");
            }
            stringBuilder.append(String.format("%s=%s", formatText.getmKey(), formatText.getmValue()));
        }
        stringBuilder.append(SESSION_KEY_DEFAULT_VALUE);
        return digestMD5(stringBuilder.toString());
    }

    public static String getCommonParam() {
        StringBuffer sb = new StringBuffer();
        YdlUserInfo userInfo = YdlCommonRouterManager.INSTANCE.getYdlCommonRoute().getUserInfo();
        sb.append(FFROM).append("=").append(YdlDataManager.INSTANCE.getRam().getChannelName())
                .append("&").append(IS_FROM_APP).append("=").append("1")
                .append("&").append(OS_BUILD).append("=").append(RxDeviceTool.getBuildBrandModel()).append(",").append(RxDeviceTool.getSDKVersionName()).append(",").append(RxAppTool.getAppVersionName(BaseApplication.Companion.getApp()))
                .append("&").append(TS).append("=").append(System.currentTimeMillis() / 1000)
                .append("&").append(VERSION).append("=").append(RxAppTool.getAppVersionName(BaseApplication.Companion.getApp()));
        if (null != userInfo) {
            sb.append("&").append(UID).append("=").append(userInfo.getUserId())
                    .append("&").append(TOKEN).append("=").append(userInfo.getToken());
        }
        return sb.toString();
    }

    //用来命名排序规则的
    static class SortData implements Comparator<FormatText> {

        @Override
        public int compare(FormatText lhs, FormatText rhs) {
            int res = lhs.getmKey().compareTo(rhs.getmKey());
            if (res == 0) {
                return 0;
            }
            return res > 0 ? -1 : 1;

        }
    }

    public static List<FormatText> getPostList(BaseCommand crq) {
        List<FormatText> formTextList = new ArrayList<>();
        Field[] fields = crq.getClass().getFields();
        for (Field field : fields) {
            try {
                boolean accessFlag = field.isAccessible();
                field.setAccessible(true);
                Object o = field.get(crq);
                if (o != null) {
                    FormatText formatText;
                    formatText = new FormatText(field.getName(), String.valueOf(o));
                    formTextList.add(formatText);
                }
                field.setAccessible(accessFlag);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return formTextList;
    }
}