package com.liquidnet.service.adam.controller;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.dypnsapi.model.v20170525.GetMobileRequest;
import com.aliyuncs.dypnsapi.model.v20170525.GetMobileResponse;
import com.aliyuncs.exceptions.ClientException;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import com.liquidnet.common.cache.redis.util.RedisUtil;
import com.liquidnet.common.sms.constant.SmsEnum;
import com.liquidnet.common.sms.processor.SmsProcessor;
import com.liquidnet.commons.lang.constant.LnsEnum;
import com.liquidnet.commons.lang.core.JwtValidator;
import com.liquidnet.commons.lang.util.*;
import com.liquidnet.service.adam.dto.AdamThirdPartParam;
import com.liquidnet.service.adam.dto.vo.AdamLoginInfoVo;
import com.liquidnet.service.adam.dto.vo.AdamUserInfoVo;
import com.liquidnet.service.adam.service.AdamRdmService;
import com.liquidnet.service.adam.service.AdamWechatService;
import com.liquidnet.service.adam.service.IAdamUserService;
import com.liquidnet.service.adam.support.AdamUserSessionSupport;
import com.liquidnet.service.adam.support.SilentMobileOtpV2Support;
import com.liquidnet.service.base.ErrorMapping;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.base.UserPathDto;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.util.DigestUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Arrays;
import java.util.Map;
import java.util.Objects;

@ApiSupport(order = 10010)
@Api(tags = "用户登录")
@Slf4j
@Validated
@RestController
@RequestMapping("")
public class AdamLoginController {
    @Autowired
    Environment env;
    @Value("${liquidnet.reviewer.user-info}")
    private Boolean reviewUserInfo;

    @Autowired
    RedisUtil redisUtil;
    @Autowired
    JwtValidator jwtValidator;
    @Autowired
    DefaultAcsClient defaultAcsClient;
    @Autowired
    AdamRdmService adamRdmService;
    @Autowired
    IAdamUserService adamUserService;
    @Autowired
    SmsProcessor smsProcessor;
    @Autowired
    AdamWechatService adamWechatService;
    @Autowired
    AdamUserSessionSupport adamUserSessionSupport;
    @Autowired
    SilentMobileOtpV2Support silentMobileOtpV2Support;

    @Value("${liquidnet.reviewer.app-login.mobile}")
    private String reviewMobile;

    @Value("${liquidnet.secret.passwd-salt}")
    private String passwdSalt;

    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "发送验证码")
    @ApiImplicitParams({
            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "mobile", value = "手机号"),
    })
    @GetMapping(value = {"send"})
    public ResponseDto<Object> sendSms(@Pattern(regexp = "\\d{11}", message = "手机号格式有误") @RequestParam String mobile) {
        log.debug("send to mobile:{}", mobile);

        String smsCodeByMobile = adamRdmService.getSmsCodeByMobile(mobile);

        if (StringUtils.isNotEmpty(smsCodeByMobile)) {
            return ResponseDto.failure(ErrorMapping.get("10000"));
        }

        String cliIpAddr = CurrentUtil.getCliIpAddr();
        log.info("cliIpAddr: {}", cliIpAddr);

        String smsCode = RandomStringUtils.randomNumeric(6);
        ObjectNode msgNode = JsonUtils.OM().createObjectNode();
        msgNode.put("code", smsCode);
        boolean sendRst = smsProcessor.send(mobile, SmsEnum.ADSignName.M02.getVal(), SmsEnum.ADTemplate.SMS_221055862.name(), msgNode.toString());
        if (sendRst) {
            adamRdmService.setSmsCodeByMobile(mobile, smsCode);

            return ResponseDto.success();
        }
        return ResponseDto.failure(ErrorMapping.get("10002"));
    }

    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "手机号密码登录")
    @ApiImplicitParams({
            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "mobile", value = "手机号"),
            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "password", value = "登录密码（只针对PHP老用户，新用户无此功能）"),
    })
    @PostMapping(value = {"login/pin"})
    public ResponseDto<AdamLoginInfoVo> loginByPin(@Pattern(regexp = "\\d{11}", message = "手机号格式有误")
                                                   @RequestParam String mobile,
                                                   @RequestParam String password) {
        log.info("mobile:{},passwd:{}", mobile, password);

        String uid = adamRdmService.getUidByMobile(mobile);
        if (StringUtils.isEmpty(uid)) {
            return ResponseDto.failure(ErrorMapping.get("10003"));
        }

        AdamUserInfoVo userInfoVo = adamRdmService.getUserInfoVoByUid(uid);
        if (null == userInfoVo || userInfoVo.getState() == 2) {
            log.warn("Cancelled mobile:{}", mobile);
            return ResponseDto.failure(ErrorMapping.get("10024"));
        }

        String passwdMd5 = DigestUtils.md5DigestAsHex(password.toLowerCase().concat(passwdSalt).getBytes(StandardCharsets.UTF_8));
        if (!passwdMd5.equals(userInfoVo.getPasswd())) {// 密码校验
            return ResponseDto.failure(ErrorMapping.get("10013"));
        }

        AdamLoginInfoVo loginInfoVo = AdamLoginInfoVo.getNew();
        loginInfoVo.setToken(this.ssoProcess(userInfoVo));
        loginInfoVo.setUserInfo(userInfoVo);
        loginInfoVo.setUserMemberVo(adamRdmService.getUserMemberVoByUid(userInfoVo.getUid()));

        log.info(UserPathDto.setData("LOGIN", ServletUtils.getRequest().getParameterMap(), loginInfoVo));
//        return ResponseDto.success(loginInfoVo.desensitize(reviewUserInfo).finalRating());
        return this.loginVoResponseProcessing(loginInfoVo);
    }

    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "手机验证码登录")
    @ApiImplicitParams({
            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "mobile", value = "手机号"),
            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "code", value = "验证码"),
            @ApiImplicitParam(type = "form", required = false, dataType = "Integer", name = "skip", value = "是否跳过完善资料[1-跳过]"),
    })
    @PostMapping(value = {"login/sms"})
    public ResponseDto<AdamLoginInfoVo> loginBySms(@Pattern(regexp = "\\d{11}", message = "手机号格式有误")
                                                   @RequestParam String mobile,
                                                   @Pattern(regexp = "\\d{6}", message = "验证码格式有误")
                                                   @RequestParam String code, @RequestParam(required = false) Integer skip) {
        log.info("mobile:{},code:{}", mobile, code);
        ResponseDto<AdamLoginInfoVo> checkSmsCodeDto = this.checkSmsCode(mobile, code);
        if (!checkSmsCodeDto.isSuccess()) return checkSmsCodeDto;

        String uid = adamRdmService.getUidByMobile(mobile);
        boolean toRegister = StringUtils.isEmpty(uid);

        AdamUserInfoVo userInfoVo = toRegister ? adamUserService.register(mobile) : adamRdmService.getUserInfoVoByUid(uid);

        if (!toRegister && (null == userInfoVo || userInfoVo.getState() == 2)) {
            log.warn("Cancelled mobile:{}", mobile);
            return ResponseDto.failure(ErrorMapping.get("10024"));
        }

        if (0 == userInfoVo.getIsComplete() && null != skip && 1 == skip) {
            // 根据skip值，设置IsComplete（考虑到已存在用户未完善信息的情况，这里只对返回数据单独设置IsComplete）
            userInfoVo.setIsComplete(1);
        }

        AdamLoginInfoVo loginInfoVo = AdamLoginInfoVo.getNew();
        loginInfoVo.setToken(this.ssoProcess(userInfoVo));
        loginInfoVo.setUserInfo(userInfoVo);
        if (!toRegister) {
            loginInfoVo.setUserMemberVo(adamRdmService.getUserMemberVoByUid(userInfoVo.getUid()));
        }

        log.info(UserPathDto.setData(toRegister ? "REGIST" : "LOGIN", ServletUtils.getRequest().getParameterMap(), loginInfoVo));
//        return ResponseDto.success(loginInfoVo.desensitize(reviewUserInfo).finalRating());
        return this.loginVoResponseProcessing(loginInfoVo);
    }

    @ApiOperationSupport(order = 4)
    @ApiOperation(value = "手机号一键登录")
    @ApiImplicitParams({
            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "accessToken", value = "访问令牌"),
    })
    @PostMapping(value = {"login/mobile"})
    public ResponseDto<AdamLoginInfoVo> loginByMobile(@NotBlank(message = "访问令牌不能为空") @RequestParam String accessToken) {
        log.debug("login by mobile access token:{}", accessToken);
        String mobile = this.getMobile(accessToken);
        if (StringUtils.isEmpty(mobile)) return ResponseDto.failure(ErrorMapping.get("10005"));

        String uid = adamRdmService.getUidByMobile(mobile);
        boolean toRegister = StringUtils.isEmpty(uid);

        AdamUserInfoVo userInfoVo = toRegister ? adamUserService.register(mobile) : adamRdmService.getUserInfoVoByUid(uid);

        if (!toRegister && (null == userInfoVo || userInfoVo.getState() == 2)) {
            log.warn("Cancelled mobile:{}", mobile);
            return ResponseDto.failure(ErrorMapping.get("10024"));
        }

        AdamLoginInfoVo loginInfoVo = AdamLoginInfoVo.getNew();
        loginInfoVo.setToken(this.ssoProcess(userInfoVo));
        loginInfoVo.setUserInfo(userInfoVo);
        if (!toRegister) {
            loginInfoVo.setUserMemberVo(adamRdmService.getUserMemberVoByUid(userInfoVo.getUid()));
        }

        log.info(UserPathDto.setData(toRegister ? "REGIST" : "LOGIN", ServletUtils.getRequest().getParameterMap(), loginInfoVo));
//        return ResponseDto.success(loginInfoVo.desensitize(reviewUserInfo).finalRating());
        return this.loginVoResponseProcessing(loginInfoVo);
    }

//    @ApiOperationSupport(order = 5)
//    @ApiOperation(value = "微信小程序登录")
//    @ApiImplicitParams({
//            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "anum", value = "应用标识[1-正在｜2-草莓音乐节｜3-五百里｜4-MDSK]", allowableValues = "1,2,3,4"),
//            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "code", value = "临时票据"),
//            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "encryptedData", value = "访问令牌"),
//            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "iv", value = "访问令牌"),
//    })
//    @PostMapping(value = {"login/wca"})
//    public ResponseDto<AdamLoginInfoVo> loginByWechatApplet(@RequestParam Integer anum,
//                                                            @RequestParam String code,
//                                                            @RequestParam String encryptedData,
//                                                            @RequestParam String iv) {
//        log.info("login by wechat applet:[anum:{},code:{},encryptedData:{},iv:{}]", anum, code, encryptedData, iv);
//        String wechatMobile, wechatOpenid, wechatUnionid;
//        try {
//            WxMaJscode2SessionResult wxMaJscode2SessionResult = adamWechatService.sessionInfo(code, anum);
//
//            WxMaPhoneNumberInfo wxMaPhoneNumberInfo = adamWechatService.phoneNumberInfo(wxMaJscode2SessionResult.getSessionKey(), encryptedData, iv, anum);
//
//            wechatMobile = wxMaPhoneNumberInfo.getPurePhoneNumber();
//            wechatOpenid = wxMaJscode2SessionResult.getOpenid();
//            wechatUnionid = wxMaJscode2SessionResult.getUnionid();
//        } catch (WxErrorException e) {
//            log.error("login by wechat applet exception:[anum:{},code:{},encryptedData:{},iv:{}], errmsg:{}", anum, code, encryptedData, iv, e.getMessage());
//            return ResponseDto.failure(ErrorMapping.get("10001"));
//        }
//
//        if (StringUtils.isEmpty(wechatMobile)) return ResponseDto.failure(ErrorMapping.get("10005"));
//
//        String uid = adamRdmService.getUidByMobile(wechatMobile);
//        boolean toRegister = StringUtils.isEmpty(uid);
//
//        AdamUserInfoVo userInfoVo = toRegister ? adamUserService.register(wechatMobile) : adamRdmService.getUserInfoVoByUid(uid);
//
//        if (!toRegister && (null == userInfoVo || userInfoVo.getState() == 2)) {
//            log.warn("Cancelled mobile:{}", wechatMobile);
//            return ResponseDto.failure(ErrorMapping.get("10024"));
//        }
//
//        // 根据skip值，设置IsComplete（考虑到已存在用户未完善信息的情况，这里只对返回数据单独设置IsComplete）
//        userInfoVo.setIsComplete(1);
//
//        AdamLoginInfoVo loginInfoVo = AdamLoginInfoVo.getNew();
//        loginInfoVo.setToken(this.ssoProcess(userInfoVo));
//        loginInfoVo.setUserInfo(userInfoVo);
//        if (!toRegister) {
//            loginInfoVo.setUserMemberVo(adamRdmService.getUserMemberVoByUid(userInfoVo.getUid()));
//        }
//        loginInfoVo.setWechatOpenid(wechatOpenid);
//        loginInfoVo.setWechatUnionid(wechatUnionid);
//
//        log.info(UserPathDto.setData(toRegister ? "REGIST" : "LOGIN", ServletUtils.getRequest().getParameterMap(), loginInfoVo));
////        return ResponseDto.success(loginInfoVo.desensitize(reviewUserInfo).finalRating());
//        return this.loginVoResponseProcessing(loginInfoVo);
//    }

    @ApiOperationSupport(order = 6)
    @ApiOperation(value = "第三方账号登录")
    @PostMapping(value = {"login/tpa"})
    public ResponseDto<AdamLoginInfoVo> loginByThirdPartApp(@Valid @RequestBody AdamThirdPartParam parameter) {
        log.info("login by tpa:{}", JsonUtils.toJson(parameter));
        boolean toRegister = false;
        AdamLoginInfoVo loginInfoVo = AdamLoginInfoVo.getNew();
        if (StringUtils.isEmpty(parameter.getMobile())) {
            String uid = adamRdmService.getUidByPlatformOpenId(parameter.getPlatform(), parameter.getOpenId());
            if (StringUtils.isEmpty(uid)) return ResponseDto.failure(ErrorMapping.get("10006"));

            AdamUserInfoVo userInfoVo = adamRdmService.getUserInfoVoByUid(uid);
            if (null == userInfoVo || userInfoVo.getState() == 2) {
                log.warn("Cancelled openId:{}", parameter.getOpenId());
                return ResponseDto.failure(ErrorMapping.get("10024"));
            }

            loginInfoVo.setUserInfo(userInfoVo);
            loginInfoVo.setUserMemberVo(adamRdmService.getUserMemberVoByUid(uid));
        } else {// 新账号注册
            ResponseDto<AdamLoginInfoVo> checkSmsCodeDto = this.checkSmsCode(parameter.getMobile(), parameter.getCode());
            if (!checkSmsCodeDto.isSuccess()) {
                return checkSmsCodeDto;
            }
            ResponseDto<AdamUserInfoVo> registerRespDto = adamUserService.register(parameter);
            if (!registerRespDto.isSuccess()) {
                return ResponseDto.failure(registerRespDto.getCode(), registerRespDto.getMessage());
            } else {
                AdamUserInfoVo registerUserInfo = registerRespDto.getData();
                loginInfoVo.setUserInfo(registerUserInfo);
//                loginInfoVo.setThirdPartInfo(adamRdmService.getThirdPartVoListByUid(registerUserInfo.getUid()));
            }
            toRegister = true;
        }
        loginInfoVo.setToken(this.ssoProcess(loginInfoVo.getUserInfo()));

        log.info(UserPathDto.setData(toRegister ? "REGIST" : "LOGIN", ServletUtils.getRequest().getParameterMap(), loginInfoVo));
//        return ResponseDto.success(loginInfoVo.desensitize(reviewUserInfo).finalRating());
        return this.loginVoResponseProcessing(loginInfoVo);
    }

    @ApiOperationSupport(order = 7)
    @ApiOperation(value = "手机号静默登录")
    @ApiImplicitParams({
            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "mobile", value = "手机号"),
            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "otp", value = "临时票据"),
    })
    @PostMapping(value = {"login/silent_mobile"})
    public ResponseDto<AdamLoginInfoVo> loginBySilentMobile(@Pattern(regexp = "\\d{11}", message = "手机号格式有误")
                                                            @NotBlank(message = "手机号不能为空")
                                                            @RequestParam String mobile,
                                                            @NotBlank(message = "临时票据不能为空")
                                                            @RequestParam String otp) {
        log.info("login by silent for mobile:{},{}", mobile, otp);
        long reql = 0, l = LocalDateTime.now().toEpochSecond(ZoneOffset.UTC);
        String otpDecrypt = null;
        try {
            otpDecrypt = DESUtils.DES().decrypt(otp);
            reql = Long.parseLong(otpDecrypt.substring(11));
        } catch (Exception e) {
        }
        if (l - reql > 10 || (null != otpDecrypt && !otpDecrypt.substring(0, 11).equals(mobile))) {
            log.error("login by silent for mobile:{},{}/{},{}-{}", mobile, otp, otpDecrypt, l, reql);
            return ResponseDto.failure(ErrorMapping.get("10005"));
        }
        return this.silentMobileLoginSuccess(mobile);
    }

    @ApiOperationSupport(order = 7)
    @ApiOperation(value = "手机号静默登录 v2（HMAC）")
    @ApiImplicitParams({
            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "mobile", value = "手机号"),
            @ApiImplicitParam(type = "form", required = true, dataType = "String", name = "otp", value = "HMAC-SHA256 十六进制，64 位"),
    })
    @PostMapping(value = {"login/silent_mobile_v2"})
    public ResponseDto<AdamLoginInfoVo> loginBySilentMobileV2(@Pattern(regexp = "\\d{11}", message = "手机号格式有误")
                                                              @NotBlank(message = "手机号不能为空")
                                                              @RequestParam String mobile,
                                                              @NotBlank(message = "临时票据不能为空")
                                                              @RequestParam String otp) {
        log.info("login by silent v2 for mobile:{}", mobile);
        if (!silentMobileOtpV2Support.verify(mobile, otp)) {
            log.error("login by silent v2 otp invalid, mobile:{}", mobile);
            return ResponseDto.failure(ErrorMapping.get("10005"));
        }
        return this.silentMobileLoginSuccess(mobile);
    }

    private ResponseDto<AdamLoginInfoVo> silentMobileLoginSuccess(String mobile) {
        String uid = adamRdmService.getUidByMobile(mobile);
        boolean toRegister = StringUtils.isEmpty(uid);

        AdamUserInfoVo userInfoVo = toRegister ? adamUserService.register(mobile) : adamRdmService.getUserInfoVoByUid(uid);

        if (!toRegister && (null == userInfoVo || userInfoVo.getState() == 2)) {
            log.warn("Cancelled mobile:{}", mobile);
            return ResponseDto.failure(ErrorMapping.get("10024"));
        }

        AdamLoginInfoVo loginInfoVo = AdamLoginInfoVo.getNew();
        loginInfoVo.setToken(this.ssoProcess(userInfoVo));
        loginInfoVo.setUserInfo(userInfoVo);
        if (!toRegister) {
            loginInfoVo.setUserMemberVo(adamRdmService.getUserMemberVoByUid(userInfoVo.getUid()));
        }

        log.info(UserPathDto.setData(toRegister ? "REGIST" : "LOGIN", ServletUtils.getRequest().getParameterMap(), loginInfoVo));
        return this.loginVoResponseProcessing(loginInfoVo);
    }

    @ApiOperationSupport(order = 7)
    @ApiOperation(value = "登出")
    @PostMapping(value = {"out"})
    public void logout() {
        log.info("###logout_uid:{}", CurrentUtil.getCurrentUid());

        String token = CurrentUtil.getToken();
        if (StringUtils.isNotBlank(token)) {
            try {
                String jti = jwtValidator.parse(token).getId();
                if (StringUtils.isNotBlank(jti)) {
                    adamUserSessionSupport.unbindSession(jti, CurrentUtil.getCurrentUid());
                }
            } catch (Exception e) {
                log.warn("logout parse token failed", e);
            }
        }
    }

    @ApiOperationSupport(order = 8)
    @ApiOperation(value = "注销")
    @PostMapping(value = {"close"})
    public ResponseDto<Object> close() {
//        log.info("###close_uid:{}", CurrentUtil.getCurrentUid());
//
//        this.logout();
//
//        adamUserService.close(CurrentUtil.getCurrentUid());

        return ResponseDto.success();
    }

    @ApiOperationSupport(order = 9)
    @ApiOperation(value = "时间戳")
    @GetMapping(value = {"ts"})
    public ResponseDto<Long> timestamp() {
        return ResponseDto.success(LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli());
    }

//    @ApiOperationSupport(order = 10)
//    @ApiOperation(value = "微信小程序登录凭证校验", notes = "这里仅用于获取OPENID使用。登录凭证校验。通过 wx.login 接口获得临时登录凭证 code 后传到开发者服务器调用此接口完成登录流程。更多使用方法详见 https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html")
//    @GetMapping(value = {"wxa/code2session"})
//    public ResponseDto<String> wxaCode2Session(@RequestParam String jsCode) {
//        String openId = null, respJStr = null;
//        try {
//            String url = AdamWechatConst.API_URL_JS_CODE2SESSION.replace("APPID", AdamWechatConst.zhengzaiAppletAppid)
//                    .replace("SECRET", AdamWechatConst.zhengzaiAppletSecret).replace("JSCODE", jsCode);
//            log.debug("jsCode={},url={}", jsCode, url);
//            respJStr = HttpUtil.get(url, null);
//            JsonNode respJNode = JsonUtils.fromJson(respJStr, JsonNode.class), respErrcode;
//            if (null == respJNode || (((respErrcode = respJNode.get("errcode")) != null) && !"0".equalsIgnoreCase(respErrcode.asText()))) {
//                log.warn("WX.API调用失败[{}]", respJStr);
//                return ResponseDto.success(null);
//            }
//            openId = respJNode.get("openid").asText();
//        } catch (Exception e) {
//            log.error("WX.API调用异常[jsCode:{},respJStr={}]", jsCode, respJStr, e);
//        }
//        log.debug("jsCode={},respJStr={}", jsCode, respJStr);
//        return ResponseDto.success(openId);
//    }
//
//    @ApiOperationSupport(order = 11)
//    @ApiOperation(value = "微信网站应用登录", notes = "这里仅用于获取OPENID使用。方法详见 https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html")
//    @GetMapping(value = {"wx/oauth2/access_token"})
//    public ResponseDto<String> wxOauth2AccessToken(@RequestParam String code) {
//        String openId = null, respJStr = null;
//        try {
//            String url = AdamWechatConst.API_URL_OAUTH2_ACCESS_TOKEN.replace("APPID", AdamWechatConst.zhengzaiServiceAppid)
//                    .replace("SECRET", AdamWechatConst.zhengzaiServiceSecret).replace("CODE", code);
//            log.debug("code={},url={}", code, url);
//            respJStr = HttpUtil.get(url, null);
//            JsonNode respJNode = JsonUtils.fromJson(respJStr, JsonNode.class), respErrcode;
//            if (null == respJNode || (((respErrcode = respJNode.get("errcode")) != null) && !"0".equalsIgnoreCase(respErrcode.asText()))) {
//                log.warn("WX.API调用失败[{}]", respJStr);
//                return ResponseDto.success(null);
//            }
//            openId = respJNode.get("openid").asText();
//        } catch (Exception e) {
//            log.error("WX.API调用异常[jsCode:{},respJStr={}]", code, respJStr, e);
//        }
//        log.debug("code={},respJStr={}", code, respJStr);
//        return ResponseDto.success(openId);
//    }

    /* ---------------------------- Internal Method ---------------------------- */
    /* ---------------------------- Internal Method ---------------------------- */
    /* ---------------------------- Internal Method ---------------------------- */

    private ResponseDto<AdamLoginInfoVo> checkSmsCode(String mobile, String code) {
        if (!LnsEnum.ENV.prod.name().equals(env.getProperty(CurrentUtil.CK_ENV_ACTIVE))
                || reviewMobile.equals(mobile)) {
            if (CurrentUtil.GRAY_LOGIN_SMS_CODE.equals(code)) {
                return ResponseDto.success();
            }
        }

        String smsCodeByMobile = adamRdmService.getSmsCodeByMobile(mobile);
        if (null == smsCodeByMobile) {
            return ResponseDto.failure(ErrorMapping.get("10004"));
        }
        return smsCodeByMobile.equals(code) ? ResponseDto.success() : ResponseDto.failure(ErrorMapping.get("10004"));
    }

    private String getMobile(String accessToken) {
        try {
            GetMobileRequest request = new GetMobileRequest();
            request.setAccessToken(accessToken);

            GetMobileResponse response = defaultAcsClient.getAcsResponse(request);

            if (!Objects.isNull(response) && response.getCode().equalsIgnoreCase("OK")) {
                return response.getGetMobileResultDTO().getMobile();
            }
            log.warn("aliyun.dypns.api.response:{},{}", JsonUtils.toJson(response), accessToken);
        } catch (ClientException e) {
            log.error("aliyun.dypns.api:{}", accessToken, e);
        }
        return null;
    }

    private String ssoProcess(AdamUserInfoVo userInfoVo) {
        Map<String, Object> claimsMap = CollectionUtil.mapStringObject();
        claimsMap.put(CurrentUtil.TOKEN_SUB, userInfoVo.getUid());
        claimsMap.put(CurrentUtil.TOKEN_MOBILE, userInfoVo.getMobile());
        claimsMap.put(CurrentUtil.TOKEN_NICKNAME, userInfoVo.getNickname());
        claimsMap.put(CurrentUtil.TOKEN_TYPE, CurrentUtil.TOKEN_TYPE_VAL_USER);
        claimsMap.put(CurrentUtil.TOKEN_UCREATED, DateUtil.Formatter.yyyyMMddHHmmssTrim.format(userInfoVo.getCreateAt()));

        log.debug("Gentoken:{}", claimsMap);

        String jti = jwtValidator.generateJti();
        String token = jwtValidator.create(claimsMap, jti);
        adamUserSessionSupport.bindSession(jti, userInfoVo.getUid());
        return token;
    }

    private ResponseDto<AdamLoginInfoVo> loginVoResponseProcessing(AdamLoginInfoVo loginInfoVo) {
        AdamUserInfoVo userInfo = loginInfoVo.getUserInfo();
        adamRdmService.ratingProvince(userInfo);
//        loginInfoVo.setBizAcctVoList(adamRdmService.getBizAcctVosByUid(userInfo.getUid()));
        return ResponseDto.success(loginInfoVo.desensitize(reviewUserInfo).finalRating());
    }
}
