package com.zhiqiyun.open.router.apis;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.dliyun.oap.framework.annotation.ServiceMethod;
import com.dliyun.oap.framework.annotation.ServiceMethodBean;
import com.dliyun.oap.framework.response.OapResponse;
import com.zhiqiyun.open.core.service.SystemConfigService;
import com.zhiqiyun.open.router.request.Oauth2LoginRequest;
import com.zhiqiyun.open.router.request.Oauth2RefreshTokenRequest;
import com.zhiqiyun.open.router.request.Oauth2UserInfoRequest;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@Slf4j
@ServiceMethodBean
public class Oauth2Api {

    @Autowired
    private OkHttpClient okHttpClient;

    @Autowired
    private SystemConfigService systemConfigService;

    @ServiceMethod(method = "oauth2.login", title = "用户登录")
    public OapResponse login(Oauth2LoginRequest request) throws IOException {

        String hostAddress = this.systemConfigService.getStringValue("OAUTH2_API_CONFIG", "hostAddress");
        String tenantId = this.systemConfigService.getStringValue("OAUTH2_API_CONFIG", "tenantId");
        String clientSecret = this.systemConfigService.getStringValue("OAUTH2_API_CONFIG", "clientSecret");

        Map<String, String> paramValues = new HashMap<>();
        paramValues.put("grant_type", "password");
        paramValues.put("username", request.getUserName());
        paramValues.put("password", DigestUtils.md5Hex(request.getPassword()));
        paramValues.put("scope", "all");
        paramValues.put("tenantId", tenantId);
        FormBody.Builder formBuilder = new FormBody.Builder();
        paramValues.forEach(formBuilder::add);


        Request.Builder builder = new Request.Builder();
        builder.url(String.format("%s/blade-auth/oauth/token", hostAddress));
        builder.header("Authorization", "Basic " + clientSecret);
        builder.header("Content-Type", "application/x-www-form-urlencoded");
        builder.header("Tenant-Id", tenantId);
        builder.post(formBuilder.build());

        Response resp = this.okHttpClient.newCall(builder.build()).execute();
        if (resp.isSuccessful()) {
            String result = Objects.requireNonNull(resp.body()).string();
            JSONObject jsonObject = JSON.parseObject(result);
            return OapResponse.success().setBody(jsonObject);
        } else {
            try {
                String result = Objects.requireNonNull(resp.body()).string();
                JSONObject jsonObject = JSON.parseObject(result);
                return OapResponse.fail(jsonObject.getString("error"), jsonObject.getString("error_description"));
            } catch (Exception e) {
                return OapResponse.fail("NETWORK_ERROR", "网络异常" + resp.message());
            }
        }
    }

    @ServiceMethod(method = "oauth2.refresh.token", title = "刷新Token")
    public OapResponse refreshToken(Oauth2RefreshTokenRequest request) throws IOException {

        String hostAddress = this.systemConfigService.getStringValue("OAUTH2_API_CONFIG", "hostAddress");
        String tenantId = this.systemConfigService.getStringValue("OAUTH2_API_CONFIG", "tenantId");
        String clientSecret = this.systemConfigService.getStringValue("OAUTH2_API_CONFIG", "clientSecret");

        FormBody.Builder formBuilder = new FormBody.Builder();
        Map<String, String> paramValues = new HashMap<>();
        paramValues.put("grant_type", "refresh_token");
        paramValues.put("scope", "all");
        paramValues.put("refresh_token", request.getRefreshToken());
        paramValues.forEach(formBuilder::add);


        Request.Builder builder = new Request.Builder();
        builder.url(String.format("%s/blade-auth/oauth/token", hostAddress));
        builder.header("Authorization", "Basic " + clientSecret);
        builder.header("Content-Type", "application/x-www-form-urlencoded");
        builder.header("Tenant-Id", tenantId);
        builder.post(formBuilder.build());

        Response resp = this.okHttpClient.newCall(builder.build()).execute();
        if (resp.isSuccessful()) {
            String result = Objects.requireNonNull(resp.body()).string();
            JSONObject jsonObject = JSON.parseObject(result);
            return OapResponse.success().setBody(jsonObject);
        } else {
            try {
                String result = Objects.requireNonNull(resp.body()).string();
                JSONObject jsonObject = JSON.parseObject(result);
                return OapResponse.fail(jsonObject.getString("error"), jsonObject.getString("error_description"));
            } catch (Exception e) {
                return OapResponse.fail("NETWORK_ERROR", "网络异常" + resp.message());
            }
        }
    }

    @ServiceMethod(method = "oauth2.user.info", title = "获取用户信息")
    public OapResponse userInfo(Oauth2UserInfoRequest request) throws IOException {


        String hostAddress = this.systemConfigService.getStringValue("OAUTH2_API_CONFIG", "hostAddress");
        String tenantId = this.systemConfigService.getStringValue("OAUTH2_API_CONFIG", "tenantId");

        Request.Builder builder = new Request.Builder();
        builder.url(String.format("%s/blade-auth/oauth/user-info", hostAddress));
        builder.header("Authorization", "bearer " + request.getAccessToken());
        builder.header("Content-Type", "application/x-www-form-urlencoded");
        builder.header("Tenant-Id", tenantId);

        Response resp = this.okHttpClient.newCall(builder.build()).execute();
        if (resp.isSuccessful()) {
            String result = Objects.requireNonNull(resp.body()).string();
            JSONObject jsonObject = JSON.parseObject(result);
            String code = jsonObject.getString("code");
            String msg = jsonObject.getString("msg");
            JSONObject data = jsonObject.getJSONObject("data");

            if (StringUtils.equals("200", code)) {
                return OapResponse.success().setBody(data);
            }
            return OapResponse.fail("REMOTE_ERROR_" + code, msg);
        } else {
            return OapResponse.fail("NETWORK_ERROR", "网络异常" + resp.message());
        }
    }
}
