package com.police.policedatasystem.http;

import static com.police.policedatasystem.util.UaCredentialApi.PARAMS_KEY_UA_APP_CREDENTIAL;
import static com.police.policedatasystem.util.UaCredentialApi.PARAMS_KEY_UA_RET_CODE;
import static com.police.policedatasystem.util.UaCredentialApi.PARAMS_KEY_UA_RET_SUCCESS;
import static com.police.policedatasystem.util.UaCredentialApi.PARAMS_KEY_UA_USER_CREDENTIAL;

import android.net.Uri;
import android.os.Bundle;

import androidx.annotation.NonNull;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.police.policedatasystem.http.requestparams.RequestParams;
import com.police.policedatasystem.http.requestparams.ResponseParams;
import com.police.policedatasystem.main.App;
import com.police.policedatasystem.main.model.ResourceList;
import com.police.policedatasystem.main.model.UserCredential;
import com.police.policedatasystem.util.Constants;
import com.police.policedatasystem.util.UiUtils;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;

public class BaseRequestClient {
    private OkHttpClient okHttpClient;
    private FindAddressCallback callback;

    public interface FindAddressCallback {
        void success();
    }

    /*

     */
    private void call(String url, RequestParams params, Callback callback) {
        try {
            RequestBody body = RequestBody.create(new Gson().toJson(params), MediaType.parse("application/json; charset=utf-8"));
            Request request = new Request.Builder()
                    .url(url)
                    .post(body)
                    .addHeader("userCredential", URLEncoder.encode(Constants.USER_CREDENTIAL, "UTF-8"))
                    .addHeader("appCredential", URLEncoder.encode(Constants.APP_CREDENTIAL, "UTF-8"))
                    .build();
            okHttpClient.newCall(request).enqueue(callback);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public void init(FindAddressCallback callback) {
        this.callback = callback;
        HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
        loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); // 设置日志级别，例如打印请求和响应的body
        okHttpClient = new OkHttpClient.Builder()
                .addInterceptor(loggingInterceptor) // 添加日志拦截器
                .callTimeout(30, TimeUnit.SECONDS)
                .connectTimeout(30, TimeUnit.SECONDS)
                .build();
        //获取接口需要用到的凭证
        getInterface();
    }

    //获取接口需要用到的凭证
    private void getInterface() {
        Uri uri = Uri.parse("content://com.ydjw.ua.getCredential");
        Bundle params = new Bundle();
        String paramsMessageId = UiUtils.uuid();
        //构建参数
        params.putString("messageId", paramsMessageId);//消息id
        params.putString("version", "1");//接口版本号，当前为1
        params.putString("appId", Constants.APP_ID);//
        params.putString("orgId", Constants.ORG_ID);//
        params.putString("networkAreaCode", "3");//
        params.putString("packageName", "com.police.policedatasystem");//应用包名，可空
        //获取票据
        Bundle bundle = App.getApp().getContentResolver().call(uri, "", null, params);
        //解析结果
        if (bundle == null) {
            UiUtils.toast("获取应用凭证失败，bundle为空！");
            return;
        }
        String messageId = bundle.getString("messageId");
        if (paramsMessageId.equals(messageId)) {
            int resultCode = bundle.getInt(PARAMS_KEY_UA_RET_CODE);
            if (PARAMS_KEY_UA_RET_SUCCESS == resultCode) {
                Constants.APP_CREDENTIAL = bundle.getString(PARAMS_KEY_UA_APP_CREDENTIAL);
                Constants.USER_CREDENTIAL = bundle.getString(PARAMS_KEY_UA_USER_CREDENTIAL);
                Constants.setUserId(new Gson().fromJson(Constants.USER_CREDENTIAL, UserCredential.class).getCredential().getLoad().getUserInfo().getJh());
                Constants.setSFZH(new Gson().fromJson(Constants.USER_CREDENTIAL, UserCredential.class).getCredential().getLoad().getUserInfo().getSfzh());
                Constants.setORG_ID(new Gson().fromJson(Constants.USER_CREDENTIAL, UserCredential.class).getCredential().getLoad().getUserInfo().getOrgId());
                //根据票据寻址
                findAddress();
            } else {
                UiUtils.toast(bundle.getString("message") + ",resultCode:" + resultCode);
            }
        } else {
            UiUtils.toast("获取应用凭证失败，messageId不一致！");
        }
    }

    //第二步，寻址
    private void findAddress() {
        Thread thread = new Thread(() -> {
            // 在这里执行耗时任务
            Uri uri = Uri.parse("content://com.ydjw.rsb.getResourceAddress");
            Bundle bundle = new Bundle();
            String paramsMessageId = UiUtils.uuid();
            bundle.putString("appCredential", Constants.APP_CREDENTIAL);//应用凭证，由上一步获得
            bundle.putString("userCredential", Constants.USER_CREDENTIAL);//用户凭证，由上一步获得
            bundle.putString("version", "1");//服务总线接口版本号，当前为1
            bundle.putString("messageId", paramsMessageId);//消息 ID
            Bundle callBack = App.getApp().getContentResolver().call(uri, "", null, bundle);
            if (callBack == null) {
                UiUtils.toast("获取应用资源地址失败,bundle为空");
                return;
            }
            String messageId = callBack.getString("messageId");
            String resourceList = callBack.getString("resourceList");
            if (paramsMessageId.equals(messageId)) {
                int resultCode = callBack.getInt("resultCode");
                if (resultCode == 0) {
                    if (UiUtils.isEmpty(resourceList)) {
                        UiUtils.toast("寻址失败，resourceList为空！");
                        return;
                    }
                    List<ResourceList> resourceLists = new Gson().fromJson(resourceList, new TypeToken<List<ResourceList>>() {
                    }.getType());
                    for (ResourceList item : resourceLists) {
                        Constants.resourceListsMap.put(item.getResourceId(), item);
                    }
                    //2.发起请求，获取重点人数据
                    if (callback != null) {
                        callback.success();
                    }
                } else {
                    if (UiUtils.isEmpty(resourceList)) {
                        UiUtils.toast("寻址失败，错误码：" + resultCode);
                    }
                }
            }
        });
        thread.start();
    }


    /**
     * 基类封装
     */
    public void request(String urlKey, String jsonParams, CustomCallBack<String> callBack) {
        ResourceList resourceList = Constants.resourceListsMap.get(urlKey);
        if (resourceList == null) {
            return;
        }
        RequestParams.Parameter parameter = getParameter(urlKey, jsonParams);
        RequestParams requestParams = new RequestParams();
        requestParams.setMessageId(UiUtils.uuid());
        requestParams.setVersion("1.0");
        requestParams.setParameter(parameter);
        call(resourceList.getResourceAddress(), requestParams, new Callback() {
            @Override
            public void onFailure(@NonNull Call call, @NonNull IOException e) {
                // 请求失败
                App.getHandler().post(() -> callBack.onError(call, e));
            }

            @Override
            public void onResponse(@NonNull Call call, @NonNull Response response) {
                if (!response.isSuccessful()) {
                    App.getHandler().post(() -> callBack.onError(call, new IOException("Unexpected code " + response)));
                    return;
                }
                try {
                    // 请求成功，处理响应数据
                    if (response.body() == null) {
                        App.getHandler().post(() -> callBack.onError(call, new Exception("服务器返回数据异常")));
                        return;
                    }
                    String responseBody = response.body().string();
                    ResponseParams responseParams = new Gson().fromJson(responseBody, ResponseParams.class);
                    if (!"200".equals(responseParams.getCode())) {
                        App.getHandler().post(() -> callBack.onError(call, new Exception("服务器出错，请联系开发人员或稍后重试！")));
                        return;
                    }
                    if (responseParams.getData().getDataList() == null || responseParams.getData().getDataList().isEmpty()) {
                        App.getHandler().post(() -> callBack.onError(call, new Exception("服务器返回数据异常")));
                        return;
                    }
                    ResponseParams.FieldData fieldData = responseParams.getData().getDataList().get(0);
                    if (fieldData.getFieldValues() == null || fieldData.getFieldValues().isEmpty()) {
                        App.getHandler().post(() -> callBack.onError(call, new Exception("服务器返回数据异常")));
                        return;
                    }
                    App.getHandler().post(() -> callBack.onSuccess(fieldData.getFieldValues().get(0).getValue()));
                } catch (Exception e) {
                    App.getHandler().post(() -> callBack.onError(call, e));
                }
            }
        });
    }

    @NonNull
    private static RequestParams.Parameter getParameter(String urlKey, String jsonParams) {
        RequestParams.Condition condition = new RequestParams.Condition();
        condition.setLogicalOperate("and");
        RequestParams.KeyValues keyValues = new RequestParams.KeyValues();
        keyValues.setKey("injson");
        keyValues.setValue(jsonParams);
        List<RequestParams.KeyValues> keyValuesList = new ArrayList<>();
        keyValuesList.add(keyValues);
        condition.setKeyValueList(keyValuesList);
        RequestParams.Parameter parameter = new RequestParams.Parameter();
        parameter.setCondition(condition);
        parameter.setPage(new RequestParams.Page());
        parameter.setFields("outjson");
        parameter.setNetworkCode("3");
        parameter.setOrderBy(null);
        parameter.setRegionalismCode(Constants.ORG_ID);
        parameter.setDataObjId(urlKey);
        return parameter;
    }
}
