package com.yzx.escreen.presenter.base;

import android.content.Intent;

import com.blankj.utilcode.util.ActivityUtils;
import com.blankj.utilcode.util.LogUtils;
import com.google.gson.stream.JsonReader;
import com.lzy.okgo.callback.AbsCallback;
import com.lzy.okgo.model.HttpHeaders;
import com.lzy.okgo.request.base.Request;
import com.yzx.escreen.App;
import com.yzx.escreen.MainActivity;
import com.yzx.escreen.activity.LoginActivity;
import com.yzx.escreen.config.RefreshToken;
import com.yzx.escreen.model.User;
import com.yzx.escreen.utils.Monitor;

import org.json.JSONArray;
import org.json.JSONObject;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Date;

import okhttp3.Response;
import okhttp3.ResponseBody;

public abstract class JsonCallBack<T> extends AbsCallback<T> {

    private Type type;
    private Class<T> clazz;
    private StringBuilder sb = new StringBuilder();

    public JsonCallBack() {

    }

    public JsonCallBack(Type type) {
        this.type = type;
    }

    public JsonCallBack(Class<T> clazz) {
        this.clazz = clazz;
    }

    @Override
    public void onStart(Request<T, ? extends Request> request) {
        super.onStart(request);
        User user = User.Companion.getUser();
        HttpHeaders headers = new HttpHeaders();
        headers.put("phone", user.getPhone());
        headers.put("token", user.getToken());
//        headers.put("phone","18780170404");
//        headers.put("token","11c73fb160bd715654736e7196dc1b57");
        request.headers(headers);

        sb.append("url：").append(request.getUrl()).append("\n");
        sb.append("headers：").append(request.getHeaders().toString()).append("\n");
        sb.append("params：").append(request.getParams().toString()).append("\n");
    }

    @Override
    public T convertResponse(Response response) throws Throwable {

        if (type == null) {
            if (clazz == null) {
                // 如果没有通过构造函数传进来，就自动解析父类泛型的真实类型（有局限性，继承后就无法解析到）
                Type genType = getClass().getGenericSuperclass();
                type = ((ParameterizedType) genType).getActualTypeArguments()[0];
            } else {
                return parseClass(response, clazz);
            }
        }

        if (type instanceof ParameterizedType) {
            return parseParameterizedType(response, (ParameterizedType) type);
        } else if (type instanceof Class) {
            return parseClass(response, (Class<?>) type);
        } else {
            return parseType(response, type);
        }
    }

    private T parseClass(Response response, Class<?> rawType) throws Exception {
        if (rawType == null) return null;
        ResponseBody body = response.body();
        if (body == null) return null;
        JsonReader jsonReader = new JsonReader(body.charStream());

        if (rawType == String.class) {
            //noinspection unchecked
            return (T) body.string();
        } else if (rawType == JSONObject.class) {
            //noinspection unchecked
            return (T) new JSONObject(body.string());
        } else if (rawType == JSONArray.class) {
            //noinspection unchecked
            return (T) new JSONArray(body.string());
        } else {
            T t = Convert.fromJson(jsonReader, rawType);
            response.close();
            return t;
        }
    }

    private T parseType(Response response, Type type) throws Exception {
        if (type == null) return null;
        ResponseBody body = response.body();
        if (body == null) return null;
        JsonReader jsonReader = new JsonReader(body.charStream());

        // 泛型格式如下： new JsonCallback<任意JavaBean>(this)
        T t = Convert.fromJson(jsonReader, type);
        response.close();
        return t;
    }

    private T parseParameterizedType(Response response, ParameterizedType type) throws Exception {
        if (type == null) return null;
        ResponseBody body = response.body();
        if (body == null) return null;
        JsonReader jsonReader = new JsonReader(body.charStream());

        Type rawType = type.getRawType();                     // 泛型的实际类型
        Type typeArgument = type.getActualTypeArguments()[0]; // 泛型的参数
        if (rawType != YzxResponse.class) {
            // 泛型格式如下： new JsonCallback<外层BaseBean<内层JavaBean>>(this)
            T t = Convert.fromJson(jsonReader, type);
            response.close();
            return t;
        } else {
            if (typeArgument == Void.class) {
                // 泛型格式如下： new JsonCallback<YzxResponse<Void>>(this)
                SimpleResponse simpleResponse = Convert.fromJson(jsonReader, SimpleResponse.class);
                response.close();
                //noinspection unchecked
                return (T) simpleResponse.toYzxResponse();
            } else {
                // 泛型格式如下： new JsonCallback<YzxResponse<内层JavaBean>>(this)
                YzxResponse yzxResponse = Convert.fromJson(jsonReader, type);
                response.close();
                int code = yzxResponse.code;
                // 一般来说服务器会和客户端约定一个数表示成功，如200，其余的表示失败，如400,300等，这里根据实际情况罗列并抛出
                if (code == 0 || code == 451 || code == 452 || code == 453) {
                    //noinspection unchecked
                    return (T) yzxResponse;
                } else if (code == 406) {
                    long currTime = new Date().getTime();
                    User.Companion.saveLastLoginTime(currTime - 24*60*60*1000L);
                    RefreshToken.INSTANCE.refresh(new RefreshToken.RefreshCallback() {
                        @Override
                        public void onSuccess() {
                            LogUtils.d("onSuccess");
                            Intent intent = new Intent(App.Companion.getContext(),MainActivity.class);
                            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                            ActivityUtils.finishActivity(MainActivity.class);
                            ActivityUtils.startActivity(intent);
                        }

                        @Override
                        public void onError() {
                            LogUtils.d("onError");
                            User.Companion.clearUserInfo();
                            Intent intent = new Intent(App.Companion.getContext(), LoginActivity.class);
                            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//                            intent.putExtra("link", Config.INSTANCE.getOA_URL()+"/login?logout=1");
                            ActivityUtils.startActivity(intent);
                            ActivityUtils.finishActivity(MainActivity.class);
                        }
                    });
                    throw new IllegalStateException("错误代码：" + code + "，错误信息：" + yzxResponse.msg);
                } else {
                    // 直接将服务端的错误信息抛出，onError中可以获取
                    throw new IllegalStateException("错误代码：" + code + "，错误信息：" + yzxResponse.msg);
                }
            }
        }
    }

    @Override
    public void onError(com.lzy.okgo.model.Response<T> response) {
        super.onError(response);
        String msg = response.getException().getMessage();
        if(msg==null){
            msg = "";
        }
        //登录相关信息不上报
        if(!msg.contains("错误代码：406") && !msg.contains("token信息不存在！")){
            sb.append("异常信息：").append(msg);
            Monitor.INSTANCE.postNetError(sb);
        }
    }
}
