package cn.iocoder.yudao.module.system.util;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.aliyun.dingtalkcontact_1_0.models.GetUserHeaders;
import com.aliyun.dingtalkcontact_1_0.models.GetUserResponse;
import com.aliyun.dingtalkoauth2_1_0.models.GetUserTokenRequest;
import com.aliyun.dingtalkoauth2_1_0.models.GetUserTokenResponse;
import com.aliyun.tea.TeaException;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.*;
import com.dingtalk.api.response.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

/**
 * @author suiyy
 * @date 20230602
 * @desc 钉钉API接口工具类
 */
@Service
public class DingtalkUtil {
    private static final Logger logger = LoggerFactory.getLogger(DingtalkUtil.class);

    /**
     * 微应用appKey
     */
    private static String APPKEY;
    @Value("${dingtalk.APP_KEY}")
    public void setAPPKEY(String APPKEY) {
        DingtalkUtil.APPKEY = APPKEY;
    }

    /**
     * 微应用appSecret
     */
    private static String APPSECRET;
    @Value("${dingtalk.APP_SECRET}")
    public void setAPPSECRET(String APPSECRET) {
        DingtalkUtil.APPSECRET = APPSECRET;
    }

    /**
     * 获取access_token
     */
    private static String GETACCESSTOKENURL;
    @Value("${dingtalk.GET_ACCESS_TOKEN_URL}")
    public void setGETACCESSTOKENURL(String GETACCESSTOKENURL) {
        DingtalkUtil.GETACCESSTOKENURL = GETACCESSTOKENURL;
    }

    /**
     * 根据钉钉用户id获取用户信息
     */
    private static String URLGETUSERINFOBYUSERID;
    @Value("${dingtalk.URL_GET_USERINFO_BYUSERID}")
    public void setURLGETUSERINFOBYUSERID(String URLGETUSERINFOBYUSERID) {
        DingtalkUtil.URLGETUSERINFOBYUSERID = URLGETUSERINFOBYUSERID;
    }

    /**
     * 通过免登授权码获取用户信息
     */
    private static String URL_GET_USERINFO_BYAUTHCODE;
    @Value("${dingtalk.URL_GET_USERINFO_BYAUTHCODE}")
    public void setURLGETUSERINFOBYAUTHCODE(String URLGETUSERINFOBYAUTHCODE) {
        DingtalkUtil.URL_GET_USERINFO_BYAUTHCODE = URLGETUSERINFOBYAUTHCODE;
    }

    /**
     * 通过UNIONID获取用户信息
     */

    private static String URLGETUSERINFOBYUNIONID;
    @Value("${dingtalk.URL_GET_USERINFO_BYUNIONID}")
    public void setURLGETUSERINFOBYUNIONID(String URLGETUSERINFOBYUNIONID) {
        DingtalkUtil.URLGETUSERINFOBYUNIONID = URLGETUSERINFOBYUNIONID;
    }

    /**
     * 获取钉钉 accessToken
     * @return
     * @throws Exception
     */
    public static String getAccessToken() throws Exception {
        DefaultDingTalkClient client = new DefaultDingTalkClient(GETACCESSTOKENURL);
        OapiGettokenRequest request = new OapiGettokenRequest();
        request.setAppkey(APPKEY);
        request.setAppsecret(APPSECRET);
        request.setHttpMethod("GET");
        OapiGettokenResponse response = client.execute(request);
        return response.getAccessToken();
    }

    public static String getUserIdByUnion(String union) throws Exception {
        String accessToken = getAccessToken();
        DingTalkClient client = new DefaultDingTalkClient(URLGETUSERINFOBYUNIONID);
        OapiUserGetbyunionidRequest req = new OapiUserGetbyunionidRequest();
        req.setUnionid(union);
        OapiUserGetbyunionidResponse rsp = client.execute(req, accessToken);
        return rsp.getResult().getUserid();
    }

        private static String URLGETUSERINFOBYMOBILE;
        @Value("${dingtalk.URL_GET_USERINFO_BYMOBILE}")
        public void setURLGETUSERINFOBYMOBILE(String URLGETUSERINFOBYMOBILE) {
            DingtalkUtil.URLGETUSERINFOBYMOBILE = URLGETUSERINFOBYMOBILE;
        }

    public static String getUserInfoByMobile(String mobile) throws Exception {
        String accessToken = getAccessToken();
        // 根据手机号获取钉钉userid
        DingTalkClient dingTalkClientUser = new DefaultDingTalkClient(URLGETUSERINFOBYMOBILE);
        OapiV2UserGetbymobileRequest phoneReq = new OapiV2UserGetbymobileRequest();
        phoneReq.setMobile(mobile);
        OapiV2UserGetbymobileResponse rsp = dingTalkClientUser.execute(phoneReq, accessToken);
        String userId = rsp.getResult().getUserid();
        return userId;
    }
    /**
     * 根据免登授权码获取用户id
     *
     * @param authCode 免登授权码
     * @return
     */
    public static String getUserIdByAuthCode(String authCode) throws Exception {
        // 1. 获取access_token
        String accessToken = getAccessToken();
        // 2. 获取用户信息
        DingTalkClient client = new DefaultDingTalkClient(URL_GET_USERINFO_BYAUTHCODE);
        OapiV2UserGetuserinfoRequest req = new OapiV2UserGetuserinfoRequest();
        req.setCode(authCode);
        OapiV2UserGetuserinfoResponse rsp = client.execute(req, accessToken);
        if (rsp.getErrcode() != 0L) {
            throw new Exception(rsp.getBody());
        }
        // 3. 返回用户id
        return rsp.getResult().getUserid();
    }

    /**
     * 根据用户id获取用户信息（用户名 工号 所属部门列表）
     *
     * @param userId 用户id
     * @return
     */
    public static OapiV2UserGetResponse.UserGetResponse getUserDetail(String userId) throws Exception {
        // 1. 获取access_token
        String accessToken = getAccessToken();
        // 2. 获取用户详情
        DingTalkClient client = new DefaultDingTalkClient(URLGETUSERINFOBYUSERID);
        OapiV2UserGetRequest req = new OapiV2UserGetRequest();
        req.setUserid(userId);
        req.setLanguage("zh_CN");
        OapiV2UserGetResponse rsp = client.execute(req, accessToken);
        if (rsp.getErrcode() != 0L) {
            throw new Exception(rsp.getBody());
        }
        // 返回用户名称rsp.getResult().getName()
        return rsp.getResult();
    }

    /**
     * 根据 临时授权码 获取用户 accessToken
     * @param code
     * @throws Exception
     */
    public static String getUserToken(String code) throws Exception {
        com.aliyun.dingtalkoauth2_1_0.Client client = createClient();
        GetUserTokenRequest getUserTokenRequest = new GetUserTokenRequest()
                .setClientId(APPKEY)
                .setClientSecret(APPSECRET)
                .setCode(code)
                .setGrantType("authorization_code");
        System.out.println("配置文件中的微应用信息：" + APPKEY + " - " + APPSECRET);
        try {
            GetUserTokenResponse userToken = client.getUserToken(getUserTokenRequest);
            System.out.println(JSON.toJSONString(userToken));
            return userToken.getBody().getAccessToken();
        } catch (TeaException err) {
            if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
                // err 中含有 code 和 message 属性，可帮助开发定位问题
                System.out.println(JSON.toJSONString(err));
            }
        } catch (Exception _err) {
            TeaException err = new TeaException(_err.getMessage(), _err);
            if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
                // err 中含有 code 和 message 属性，可帮助开发定位问题
                System.out.println(JSON.toJSONString(err));
            }
        }
        return StrUtil.EMPTY;
    }

    /**
     * 根据 accessToken 获取用户信息（特别是手机号）
     * @param accessToken
     * @throws Exception
     */
    public static String getUserInfo(String accessToken) throws Exception {
        com.aliyun.dingtalkcontact_1_0.Client client = createContactClient();
        GetUserHeaders getUserHeaders = new GetUserHeaders();
        getUserHeaders.xAcsDingtalkAccessToken = accessToken;
        try {
            GetUserResponse response = client.getUserWithOptions("me", getUserHeaders, new RuntimeOptions());
            System.out.println(JSON.toJSON(response));
            String mobile = response.getBody().getMobile();
            return mobile;
        } catch (TeaException err) {
            if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
                // err 中含有 code 和 message 属性，可帮助开发定位问题
                System.out.println(JSON.toJSONString(err));
            }
        } catch (Exception _err) {
            TeaException err = new TeaException(_err.getMessage(), _err);
            if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
                // err 中含有 code 和 message 属性，可帮助开发定位问题
                System.out.println(JSON.toJSONString(err));
            }
        }
        return StrUtil.EMPTY;
    }

    public static com.aliyun.dingtalkoauth2_1_0.Client createClient() throws Exception {
        Config config = new Config();
        config.protocol = "https";
        config.regionId = "central";
        return new com.aliyun.dingtalkoauth2_1_0.Client(config);
    }

    public static com.aliyun.dingtalkcontact_1_0.Client createContactClient() throws Exception {
        Config config = new Config();
        config.protocol = "https";
        config.regionId = "central";
        return new com.aliyun.dingtalkcontact_1_0.Client(config);
    }
}
