package com.huawei.hwmdemo.utils;

import androidx.annotation.NonNull;

import com.google.gson.Gson;
import com.huawei.hwmbiz.login.api.AppIdAuthParam;
import com.huawei.hwmdemo.constant.ConfigConstant;
import com.huawei.hwmfoundation.callback.HwmCallback;
import com.huawei.hwmlogger.HCLog;
import com.huawei.hwmsdk.enums.SDKERR;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;

import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * 登录接口的工具类
 */
public class LoginUtil {
    private static final String TAG = LoginUtil.class.getSimpleName();
    private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");

    static class AppIdAuthInfo {
        public String appId;

        public String signature;

        public String corpId;

        public String userId;

        public long expireTime;

        public String nonce;

        public int clientType;

        public String userName;

        public String userEmail;

        public String userPhone;

        public String deptCode;
    }

    private static AppIdAuthInfo toAppIdAuthorizeInfo(AppIdAuthParam appIdAuthParam) {
        AppIdAuthInfo appIdAuthorizeInfo = new AppIdAuthInfo();
        appIdAuthorizeInfo.corpId = appIdAuthParam.getCorpId();
        appIdAuthorizeInfo.signature = appIdAuthParam.getSignature();
        appIdAuthorizeInfo.appId = PreferencesUtil.getStringPreference(DemoUtil.getResContext(), ConfigConstant.KEY_APP_ID, AppIdContants.APP_ID);
        appIdAuthorizeInfo.userId = appIdAuthParam.getThirdUserId();
        appIdAuthorizeInfo.expireTime = appIdAuthParam.getExpireTime();
        appIdAuthorizeInfo.nonce = appIdAuthParam.getNonce();
        appIdAuthorizeInfo.deptCode = appIdAuthParam.getDeptCode();
        appIdAuthorizeInfo.clientType = 50;
        appIdAuthorizeInfo.userEmail = "";
        appIdAuthorizeInfo.userPhone = "";
        appIdAuthorizeInfo.userName = "";
        return appIdAuthorizeInfo;
    }

    /**
     * 通过AppIdAuthParam调用服务器接口先获取accessToken然后再获取登录nonce
     * @param appIdAuthParam
     * @param callback
     * @return
     */
    public static void getAppIdLoginNonce(@NonNull AppIdAuthParam appIdAuthParam, @NonNull LoginParamEx loginParamEx, @NonNull HwmCallback<String> callback) {
        new Thread(() -> {
            String accessToken = getLoginByAppIdAccessToken(appIdAuthParam, loginParamEx);
            if (accessToken != null) {
                String nonce = getLoginNonceByAccessToken(accessToken, loginParamEx);
                if (nonce != null) {
                    callback.onSuccess(nonce);
                } else {
                    callback.onFailed(SDKERR.UISDK_COMMON_ERROR.getValue(), "failed to get nonce:获取nonce失败");
                }
            } else {
                callback.onFailed(SDKERR.UISDK_COMMON_ERROR.getValue(), "failed to get accessToken:获取token失败");
            }
        }).start();
    }

    /**
     * 调用服务器接口获取AccessToken
     * @param appIdAuthParam
     * @return
     */
    private static String getLoginByAppIdAccessToken(AppIdAuthParam appIdAuthParam, @NonNull LoginParamEx loginParamEx) {

        OkHttpClient client = new OkHttpClient.Builder()
                .hostnameVerifier(new CustomHostnameVerifier(loginParamEx.getSSLCheck()))
                .build();
        String url = "https://" + loginParamEx.severAddress + ":" + loginParamEx.severPort + "/v2/usg/acs/auth/appauth";
        String json = new Gson().toJson(toAppIdAuthorizeInfo(appIdAuthParam));
        RequestBody body = RequestBody.create(JSON, json);
        Request request = new Request.Builder().addHeader("Authorization",
            "HMAC-SHA256 signature=" + appIdAuthParam.getSignature()).url(url).post(body).build();
        try {
            Response response = client.newCall(request).execute();
            JSONObject object = new JSONObject(response.body().string());
            String accessToken = object.getString("accessToken");
            return accessToken;
        } catch (IOException | JSONException e) {
            HCLog.i(TAG, "getLoginByAppIdAccessToken exception");
        }
        return null;
    }

    /**
     * 调用服务器接口获取登录nonce
     * @param accessToken
     * @return
     */
    private static String getLoginNonceByAccessToken(String accessToken, @NonNull LoginParamEx loginParamEx) {
        OkHttpClient client = new OkHttpClient.Builder()
                .hostnameVerifier(new CustomHostnameVerifier(loginParamEx.getSSLCheck()))
                .build();
        String url = "https://" + loginParamEx.severAddress + ":" + loginParamEx.severPort + "/v1/usg/acs/auth/portal-ref-nonce";
        RequestBody body = RequestBody.create(JSON, new JSONObject().toString());
        Request request = new Request.Builder().addHeader("X-Access-Token", accessToken).url(url).post(body).build();
        try {
            Response response = client.newCall(request).execute();
            JSONObject object = new JSONObject(response.body().string());
            String nonce = object.getString("nonce");
            return nonce;
        } catch (IOException | JSONException e) {
            HCLog.i(TAG, "getLoginNonceByAccessToken exception");
        }
        return null;
    }

    private static class CustomHostnameVerifier implements HostnameVerifier {

        private boolean isIgnoreSSLCheck;

        public CustomHostnameVerifier(boolean isSSLCheck) {
            this.isIgnoreSSLCheck = !isSSLCheck;
        }

        @Override
        public boolean verify(String hostname, SSLSession session) {
            return isIgnoreSSLCheck;
        }
    }

    public static class LoginParamEx {
        private String severAddress;

        private String severPort;

        private boolean isSSLCheck;

        public LoginParamEx(String severAddress, String severPort, boolean isSSLCheck) {
            this.severAddress = severAddress;
            this.severPort = severPort;
            this.isSSLCheck = isSSLCheck;
        }

        public String getSeverAddress() {
            return severAddress;
        }

        public void setSeverAddress(String severAddress) {
            this.severAddress = severAddress;
        }

        public String getSeverPort() {
            return severPort;
        }

        public void setSeverPort(String severPort) {
            this.severPort = severPort;
        }

        public boolean getSSLCheck() {
            return isSSLCheck;
        }

        public void setSSLCheck(boolean SSLCheck) {
            this.isSSLCheck = SSLCheck;
        }
    }
}
