package com.duiba.tuia.youtui.web.bo.impl;

import cn.com.duiba.tuia.activity.center.api.constant.BalanceRecordType;
import cn.com.duiba.tuia.activity.center.api.constant.BalanceType;
import cn.com.duiba.tuia.activity.center.api.constant.MoneySource;
import cn.com.duiba.tuia.activity.center.api.constant.SlotLoginType;
import cn.com.duiba.tuia.activity.center.api.dto.GuidePageDto;
import cn.com.duiba.tuia.activity.center.api.dto.consumer.ConsumerCache;
import cn.com.duiba.tuia.activity.center.api.dto.consumer.ConsumerDto;
import cn.com.duiba.tuia.activity.center.api.dto.consumer.UserBalanceDto;
import cn.com.duiba.tuia.activity.center.api.dto.consumer.req.BalanceRecordAdd;
import cn.com.duiba.tuia.activity.center.api.util.MathUtil;
import cn.com.duiba.tuia.activity.center.api.util.SignTool;
import cn.com.duiba.tuia.ssp.center.api.dto.MediaAppDataDto;
import cn.com.duiba.tuia.ssp.center.api.dto.PlugBuoyConfigDto;
import cn.com.duiba.tuia.ssp.center.api.dto.SlotDto;
import cn.com.duiba.wolf.utils.BeanUtils;
import cn.com.duibaboot.ext.autoconfigure.accesslog.AccessLogFilter;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.dianping.cat.Cat;
import com.duiba.tuia.youtui.web.bo.ConsumerBO;
import com.duiba.tuia.youtui.web.constant.Constants;
import com.duiba.tuia.youtui.web.constant.ErrorCode;
import com.duiba.tuia.youtui.web.constant.InnerLogCode;
import com.duiba.tuia.youtui.web.embed.CommonEmbed;
import com.duiba.tuia.youtui.web.exception.ActivityException;
import com.duiba.tuia.youtui.web.exception.BusinessException;
import com.duiba.tuia.youtui.web.log.InnerLogService;
import com.duiba.tuia.youtui.web.model.AutoLoginReq;
import com.duiba.tuia.youtui.web.model.BalanceRecordVO;
import com.duiba.tuia.youtui.web.model.CommonLoginReq;
import com.duiba.tuia.youtui.web.model.UserAccount;
import com.duiba.tuia.youtui.web.model.req.ConsumerReq;
import com.duiba.tuia.youtui.web.model.req.YiDunVerifyReq;
import com.duiba.tuia.youtui.web.model.rsp.LoginMidPageRsp;
import com.duiba.tuia.youtui.web.service.AppService;
import com.duiba.tuia.youtui.web.service.BalanceRecordService;
import com.duiba.tuia.youtui.web.service.CommonService;
import com.duiba.tuia.youtui.web.service.ConsumerService;
import com.duiba.tuia.youtui.web.service.GuidePageService;
import com.duiba.tuia.youtui.web.service.RedPacketService;
import com.duiba.tuia.youtui.web.service.SlotService;
import com.duiba.tuia.youtui.web.service.UserBalanceService;
import com.duiba.tuia.youtui.web.tongdun.FraudApiRequest;
import com.duiba.tuia.youtui.web.tongdun.FraudApiResponse;
import com.duiba.tuia.youtui.web.tool.*;
import com.duiba.tuia.youtui.web.tool.http.JsoupUtil;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.*;

/**
 * Created by Administrator on 2017/12/12.
 */
@Service
public class ConsumerBOImpl implements ConsumerBO {

    /*用户调用短信接口最大次数*/
    private static final int MAX_SMS_TIMES = 5;

    private Logger log = LoggerFactory.getLogger(ConsumerBOImpl.class);

    @Autowired
    private ConsumerService consumerService;

    @Autowired
    private CommonService commonService;

    @Autowired
    private BalanceRecordService balanceRecordService;

    @Autowired
    private UserBalanceService userBalanceService;

    @Autowired
    private SlotService slotService;

    @Autowired
    private AppService appService;

    @Autowired
    private GuidePageService guidePageService;

    /** 瓜分红包service */
    @Autowired
    private RedPacketService redPacketService;

    private static final String PHONE_PREFIX = "_phone_";
    private static final String USER_PREFIX = "_userId_";
    private static final String IP_PREFIX = "_ip_";

    @Override
    public Boolean register(ConsumerReq req, HttpServletRequest request) throws BusinessException, ActivityException {
        UserAccount userAccount = RequestLocal.get().getUserAccount();
        if (null == userAccount) {
            //拿不到用户信息，非法用户
            throw new BusinessException(ErrorCode.E0200016);
        }
        if (userAccount.getLoginStatus()) {
            //用户已登录
            throw new BusinessException(ErrorCode.E0200011);
        }
        //1.1用户已经注册，返回请直接登录
        if (null != consumerService.findFormalConsumer(userAccount.getAppId(), req.getPhone(), null)) {
            throw new BusinessException(ErrorCode.E0200009);
        }
        GuidePageDto guidePage = guidePageService.getGuidePage(req.getPageId());
        if(!BalanceType.CASH.getType().equals(guidePage.getExtInfo().getDirectType())&&
                !BalanceType.RED_PACKET.getType().equals(guidePage.getExtInfo().getDirectType())){
            //页面类型不对应
            throw new BusinessException(ErrorCode.E0200015);
        }

        //1.1用户密码错误，请重新输入
        String verCode = consumerService.getRegisterVerCode(req.getPhone());
        if (StringUtils.isBlank(verCode)) {
            throw new BusinessException(ErrorCode.E0200012);
        }
        if (!StringUtils.equals(verCode, req.getInitialPassword())) {
            throw new BusinessException(ErrorCode.E0200008);
        }
        //2.1创建正式用户，用户id采用之前的游客用户id--数据源 tuia_consumer
        ConsumerDto consumerDto = new ConsumerDto(userAccount.getAppId(), userAccount.getPartnerUserId());
        consumerDto.setPhone(req.getPhone());
        consumerDto.setInitialPassword(req.getInitialPassword());
        consumerDto.setLogin(SlotLoginType.PHONE);
        ConsumerDto newConsumer = consumerService.getOrCreateConsumer(consumerDto);
        createBalance(userAccount.getAppId(), newConsumer.getUserId(), BalanceType.CASH, slotService.getSlot(Long.valueOf(RequestLocal.get().getSlotId())).get().getPlugBuoyConfigDto(), null);
        //2.3 只迁移游客用户登陆到真实用户的明细和余额(目前只有现金钱包)
        if (BalanceType.CASH.getType().equals(req.getBalanceType())) {
            balanceRecordService.moveBalance(userAccount.getUserId(), newConsumer.getUserId(), BalanceType.CASH);
            /**
             * 增加瓜分红包迁移逻辑
             * @modify lichao 2018-3-16
             */
            redPacketService.movePopus(userAccount.getAppId(),userAccount.getUserId(), newConsumer.getUserId());
        }
        //3.1种cookie，覆盖用户信息，用户id一致校验
        userAccount.setLoginStatus(true);
        userAccount.setUserId(newConsumer.getUserId());
        RequestLocal.get().setCookie(userAccount);

        BalanceRecordAdd add = new BalanceRecordAdd();
        add.setBalanceType(BalanceType.CASH);
        add.setAmount(10l);
        add.setRecordType(BalanceRecordType.FIRST_LOGIN);
        add.setAppId(userAccount.getAppId());
        add.setPageId(req.getPageId());
        add.setUserId(newConsumer.getUserId());
        add.setSlotId(Long.valueOf(RequestLocal.get().getSlotId()));
        userBalanceService.addAmount(add);

        //4.2保存订单队列 给中间公示
        BalanceRecordVO vo = new BalanceRecordVO();
        vo.setPhone(req.getPhone());
        vo.setAmount(10L);
        balanceRecordService.putInRecentlyList(vo, 30);
        try {
            Cat.logMetricForCount("活动中心-用户成功注册");
        } catch (Exception e) {
            log.error(Constants.CAT_ERROR, e);
        }
        AccessLogFilter.putExPair("phone", req.getPhone());
        return true;
    }

    public void createBalance(Long appId, Long userId, BalanceType balanceType, PlugBuoyConfigDto slot, Long initAmount) {
        //2.2创建金币账户
        if (slot.getLoginType().equals(SlotLoginType.MEDIA.getType()) && slot.getMoneySource().equals(MoneySource.MEDIA.getType())) {
            //第三方媒体金币来源时，创建账户时需要预置金币
            if (null != initAmount) {
                initAmount += Long.valueOf(initAmount) * Long.valueOf(slot.getMoneyRate());
            }
        }
        userBalanceService.createBalance(appId, userId, balanceType, initAmount);
    }

    @Override
    public void wxAutoLogin(HttpServletRequest request, PlugBuoyConfigDto slot, Long appId, String deviceId) throws ActivityException {
        UserAccount userAccount = RequestLocal.get().getUserAccount();
        if(null == userAccount || userAccount.getAppId() != appId){
            userAccount = new UserAccount(appId, deviceId);
        }
        String muId = deviceId;//威信用户id
        ConsumerCache cache = consumerService.getConsumerCache4WX(deviceId);
        //3.用户识别
        ConsumerDto formalConsumer = consumerService.findFormalConsumer(appId, null, muId);
        if (null == formalConsumer) {
            //新用户做首次登陆
            ConsumerDto consumerDto = new ConsumerDto(appId, deviceId);
            consumerDto.setMuId(muId);
            consumerDto.setLogin(SlotLoginType.WEIXIN);
            consumerDto.getExtInfo().setNickName(cache.getNickName());
            consumerDto.getExtInfo().setSex(cache.getSex());
            consumerDto.getExtInfo().setImg(cache.getImg());
            try {
                formalConsumer = consumerService.getOrCreateConsumer(consumerDto);
            } catch (ActivityException e) {
                log.warn("媒体用户自动登陆失败", e);
                throw new ActivityException(ErrorCode.E9999999);
            }
            //4.用户账户
            createBalance(appId, formalConsumer.getUserId(), BalanceType.GAME, slot, null);
        }else{
            //更新用户信息
            ConsumerDto consumerDto = new ConsumerDto();
            consumerDto.setUserId(formalConsumer.getUserId());
            ConsumerDto.ExtInfo extInfo = formalConsumer.getExtInfo();
            consumerDto.setExtInfo(null == extInfo ? new ConsumerDto.ExtInfo() : extInfo);
            consumerDto.getExtInfo().setNickName(cache.getNickName());
            consumerDto.getExtInfo().setSex(cache.getSex());
            consumerDto.getExtInfo().setImg(cache.getImg());
            consumerService.updateConsumer(consumerDto);
        }

        //旧用户种cookie，设置登陆
        userAccount.setLoginStatus(true);
        userAccount.setUserId(formalConsumer.getUserId());
        userAccount.setPartnerUserId(formalConsumer.getDeviceId());//deviceId以数据库为准
        RequestLocal.get().setCookie(userAccount);
        //处理wx用户缓存

        cache.setUserId(formalConsumer.getUserId());
        cache.setAppId(formalConsumer.getAppId());
        cache.setDeviceId(deviceId);
        consumerService.setConsumerCache(cache);
    }

    @Override
    public LoginMidPageRsp commonlogin(CommonLoginReq req,String host) throws ActivityException {
        MediaAppDataDto app;
        Optional<SlotDto> slotDtoOptional;
        try {
            slotDtoOptional = slotService.getSlot(Long.valueOf(req.getSlotId()));
            app = appService.findAppByAppKey(req.getAppKey());
        } catch (Exception e) {
            log.warn("游客自动登录非法的appkey。this error IP = " + RequestLocal.get().getIp() + " and error appKey = " + req.getAppKey());
            return null;
        }
        if (app == null || !slotDtoOptional.isPresent()) {
            throw new ActivityException(ErrorCode.E0300001);
        }
        Long appId = app.getAppId();
        PlugBuoyConfigDto slot = slotDtoOptional.get().getPlugBuoyConfigDto();
        //1.广告位登录校验,只处理普通游客登录的自登录
        if (!slot.getLoginType().equals(SlotLoginType.NORMAL.getType())) {
            log.warn("当前广告位不是cookie登陆，登陆类型为{},广告位id为{}", slot.getLoginType(), slot.getId());
            throw new ActivityException(ErrorCode.E0200018);
        }

        //3.用户识别,此时的deviceid为同盾返回的设备指纹，同盾失败情况下由前端生成，保存在客户端；
        String deviceId = req.getDeviceId();
        ConsumerDto formalConsumer = consumerService.findFormalConsumer(appId, null, deviceId);
        if (null == formalConsumer) {
            //新用户做首次登陆
            ConsumerDto consumerDto = new ConsumerDto(appId, deviceId);
            consumerDto.setMuId(deviceId);
            consumerDto.setLogin(SlotLoginType.NORMAL);
            consumerDto.getExtInfo().setNickName(consumerService.getVisitorNickName(6, 0));
            consumerDto.getExtInfo().setSex(0);
            consumerDto.getExtInfo().setImg("//yun.duiba.com.cn/h5-mami/webgame/web-login/header/newhander" + (new Random().nextInt(4) + 1) + ".png");
            try {
                formalConsumer = consumerService.getOrCreateConsumer(consumerDto);
            } catch (ActivityException e) {
                log.warn("媒体用户自动登陆失败", e);
                throw new ActivityException(ErrorCode.E9999999);
            }
            //4.创建用户账户
            createBalance(appId, formalConsumer.getUserId(), BalanceType.GAME, slot, 0l);
        }
        //5.缓存用户信息
        ConsumerDto.ExtInfo extInfo = formalConsumer.getExtInfo();
        consumerService.setConsumerCache(new ConsumerCache(formalConsumer.getUserId(), appId, extInfo.getSex(), extInfo.getNickName(), extInfo.getImg(), extInfo.getLoginType(), deviceId));
        //6.设置登录
        UserAccount userAccount = new UserAccount(appId, deviceId);
        userAccount.setLoginStatus(true);
        userAccount.setUserId(formalConsumer.getUserId());
        RequestLocal.get().setCookie(userAccount);
        CommonEmbed commonEmbed = new CommonEmbed("1019.1.0.0", "", appId + ".131.1.1", formalConsumer.getUserId(),
                appId, host);
        CommonEmbed confirmSubmission = new CommonEmbed("1019.1.0.0", "", appId + ".131.1.2", formalConsumer
                .getUserId(),appId, host);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("click",commonEmbed.clickInfo());
        jsonObject.put("exposure", commonEmbed.exposureInfo());
        jsonObject.put("confirm_submission_click",confirmSubmission.clickInfo());
        jsonObject.put("confirm_submission_exposure", confirmSubmission.exposureInfo());
        LoginMidPageRsp rsp = BeanUtils.copy(formalConsumer.getExtInfo(), LoginMidPageRsp.class);
        rsp.setEmbed(jsonObject);
        return rsp;
    }

    @Override
    public void autoLogin(AutoLoginReq req, BalanceType balanceType) throws ActivityException {
        MediaAppDataDto app;
        Optional<SlotDto> slotDtoOptional;
        try {
            slotDtoOptional = slotService.getSlot(Long.valueOf(req.getSlotId()));
            app = appService.findAppByAppKey(req.getAppKey());
        } catch (Exception e) {
            log.warn("媒体用户自动登录非法的appkey。this error IP = " + RequestLocal.get().getIp() + " and error appKey = " + req.getAppKey());
            return;
        }

        if (app == null || !slotDtoOptional.isPresent()) {
            throw new ActivityException(ErrorCode.E0300001);
        }
        Long appId = app.getAppId();
        PlugBuoyConfigDto slot = slotDtoOptional.get().getPlugBuoyConfigDto();

        //1.广告位登录校验,只处理第三方用户的自登录
        if (!slot.getLoginType().equals(SlotLoginType.MEDIA.getType())) {
            return;
        }
        //2.签名检验
        if (!signVerify(req, app.getAppSecret())) {
            throw new ActivityException(ErrorCode.E0200010);
        }
        //3.用户识别
        ConsumerDto formalConsumer = consumerService.findFormalConsumer(appId, null, req.getMuId());
        if (null == formalConsumer) {
            //新用户做首次登陆
            ConsumerDto consumerDto = new ConsumerDto(appId, req.getDeviceId());
            consumerDto.setMuId(req.getMuId());
            consumerDto.setLogin(SlotLoginType.MEDIA);
            try {
                formalConsumer = consumerService.getOrCreateConsumer(consumerDto);
            } catch (ActivityException e) {
                log.warn("媒体用户自动登陆失败", e);
                throw new ActivityException(ErrorCode.E9999999);
            }
            //4.用户账户
            createBalance(appId, formalConsumer.getUserId(), balanceType, slot, req.getCredits());
        }else{
            //5.余额更新
            //第三方金币来源时，老用户需要更新最新账户余额
            updateBalance(req, slot, formalConsumer.getUserId(), balanceType);
        }
        //6.设置登录
        UserAccount userAccount = new UserAccount(appId, req.getDeviceId());
        userAccount.setLoginStatus(true);
        userAccount.setUserId(formalConsumer.getUserId());
        RequestLocal.get().setCookie(userAccount);
    }


   private void updateBalance(AutoLoginReq req, PlugBuoyConfigDto slot, Long userId, BalanceType balanceType) {
        if (slot.getLoginType().equals(SlotLoginType.MEDIA.getType()) && slot.getMoneySource().equals(MoneySource.MEDIA.getType())){
            String credits = req.getCredits().toString();
            if (StringUtils.isNotBlank(credits)) {
                UserBalanceDto balanceDto = userBalanceService.getByType(userId, balanceType);
                Long amount = Long.valueOf(MathUtil.exchangeRate2a(slot.getMoneyRate(), Double.valueOf(credits)));
                if (amount > 0 && amount != balanceDto.getAmount()) {
                    userBalanceService.forceUpdateAmount(userId, amount, balanceType);
                }
            }
        }
    }

    /**
     * 第三方媒体提供用户的直投页签名校验
     * @param req
     * @param appSecret
     * @return
     */
    private boolean signVerify(AutoLoginReq req, String appSecret){
        Map<String, String> params = new TreeMap<>();
        params.put("muId", req.getMuId());
        String credits = req.getCredits().toString();
        if(StringUtils.isNotBlank(credits)){
            params.put("credits", credits);
        }
        params.put("appKey", req.getAppKey());
        params.put("timestamp", req.getTimestamp());
        params.put("sign", req.getSign());
        return SignTool.signVerify(appSecret, params);
    }

    @Override
    public Boolean login(ConsumerReq req, HttpServletRequest request) throws BusinessException, ActivityException {
        UserAccount userAccount = RequestLocal.get().getUserAccount();
        if (null == userAccount) {
            //拿不到用户信息，非法用户
            throw new BusinessException(ErrorCode.E0200016);
        }
        if (userAccount.getLoginStatus()) {
            //用户已登录
            throw new BusinessException(ErrorCode.E0200011);
        }
        //用户登陆尝试次数
        int loginTryTimes = consumerService.getLoginTryTimes(userAccount.getUserId().toString());

        if (3 <= loginTryTimes) {
            throw new BusinessException(ErrorCode.E0200014);
        }
        //校验用户是存在，不存在提醒注册
        ConsumerDto consumer = consumerService.findFormalConsumer(userAccount.getAppId(), req.getPhone(), null);
        if (null == consumer) {
            throw new BusinessException(ErrorCode.E0200007);
        }
        //密码不匹配，请重新输入
        if ((null != req.getPassword() && !req.getPassword().equals(consumer.getPassword()))) {
            consumerService.updateLoginTryTimes(userAccount.getUserId().toString());
            throw new BusinessException(ErrorCode.E0200008);
        }

        if (null != req.getInitialPassword() && !req.getInitialPassword().equals(consumer.getInitialPassword())) {
            String registerVerCode = consumerService.getRegisterVerCode(req.getPhone());
            if (StringUtils.equals(req.getInitialPassword(), registerVerCode)) {
                //验证码匹配时候，也登录成功
                ConsumerDto consumerDto = new ConsumerDto(userAccount.getAppId(), null);
                consumerDto.setUserId(consumer.getUserId());
                consumerDto.setInitialPassword(registerVerCode);
                consumerService.updateConsumer(consumerDto);
            } else {
                //初始密码不匹配
                consumerService.updateLoginTryTimes(userAccount.getUserId().toString());


                throw new BusinessException(ErrorCode.E0200008);
            }
        }
        //2.3 只迁移游客用户登陆到真实用户的瓜分红包
        if (BalanceType.CASH.getType().equals(req.getBalanceType())) {
            /**
             * 增加瓜分红包迁移逻辑
             * @modify lichao 2018-3-16
             */
            redPacketService.movePopus(userAccount.getAppId(),userAccount.getUserId(), consumer.getUserId());
        }

        //种cookie，覆盖用户信息
        userAccount.setLoginStatus(true);
        userAccount.setUserId(consumer.getUserId());
        RequestLocal.get().setCookie(userAccount);
        try {
            Cat.logMetricForCount("活动中心-用户成功登录");
        } catch (Exception e) {
            log.error(Constants.CAT_ERROR, e);
        }

        AccessLogFilter.putExPair("phone", req.getPhone());
        return true;
    }

    @Override
    public Boolean resetPassword(ConsumerReq req) throws ActivityException {
        UserAccount userAccount = RequestLocal.get().getUserAccount();
        ConsumerDto consumerDto = new ConsumerDto(userAccount.getAppId(), null);
        consumerDto.setUserId(userAccount.getUserId());
        consumerDto.setPassword(req.getPassword());
        return consumerService.updateConsumer(consumerDto);
    }

    @Override
    public Boolean sendSms(ConsumerReq req, String validate, Integer type) throws IOException, BusinessException, NoSuchAlgorithmException {

        //用户校验
        UserAccount userAccount = RequestLocal.get().getUserAccount();
        String userId = userAccount.getUserId().toString();
        String phone = req.getPhone();

        //已注册的手机号在注册页面点击获取验证码时应在此处校验手机号是否注册过
        ConsumerDto consumer = consumerService.findFormalConsumer(userAccount.getAppId(), phone, null);
        if (type == 1 && null != consumer) {
            throw new BusinessException(ErrorCode.E0200009);
        } else if (type == 2 && null == consumer) {
            //未注册的手机号在忘记密码页面点击获取初始密码时应该校验此密码如果是未注册的，引导去注册
            throw new BusinessException(ErrorCode.E0200007);
        }

        String ip = RequestLocal.get().getIp();
        int userTimes = consumerService.getSmsTimes(USER_PREFIX + userId);
        int phoneTimes = consumerService.getSmsTimes(PHONE_PREFIX + phone);
        int ipTimes = consumerService.getSmsTimes(IP_PREFIX + ip);
        String ipCount = commonService.getSystemConfig(Constants.TuiaKey.TUIA_SMS_IP_TIMES);
        String userAndPhoneCount = commonService.getSystemConfig(Constants.TuiaKey.TUIA_USER_SMS_TIMES);
        if ((phoneTimes >= Integer.parseInt(userAndPhoneCount) || userTimes >= Integer.parseInt(userAndPhoneCount) ||
                ipTimes >= Integer.parseInt(ipCount) || consumerService.isYiDunVerifyList(userId)) &&
                (StringUtils.isBlank(validate) || !verify(userId, validate))) {
            //触发易盾验证码的用户校验
            throw new BusinessException(ErrorCode.E0200013);
        }

        if (userTimes > MAX_SMS_TIMES || phoneTimes > MAX_SMS_TIMES) {
            throw new BusinessException(ErrorCode.E0200016);
        }
        //发送短信
        String verCode = PhoneTool.createRandom(6);
        SmsTool.sendCodeSms(req.getPhone(), Constants.SMS_TEXT.replaceFirst("\\[\\{\\}\\]", verCode));

        try {
            Cat.logMetricForCount("活动中心-短信发送量");
        } catch (Exception e) {
            log.error(Constants.CAT_ERROR, e);
        }

        //保存验证码
        consumerService.setRegisterVerCode(phone, verCode);
        //保存用户请求验证码次数
        consumerService.setSmsTimes(PHONE_PREFIX + phone, ++phoneTimes);
        consumerService.setSmsTimes(USER_PREFIX + userId, ++userTimes);
        consumerService.setSmsTimes(IP_PREFIX + ip, ++ipTimes);

        //内部日志
        innerLog(req, userAccount, userId);

        //短信调用量告警,阈值为alertThread， 超出阈值每100条报警一次
        int smsTotalTimes = consumerService.getSmsTotalTimes();
        int alertThread = Integer.valueOf(commonService.getSystemConfig(Constants.TuiaKey.TUIA_SMS_TOTAL_COUNT));
        int space = Integer.valueOf(commonService.getSystemConfig(Constants.TuiaKey.TUIA_SMS_ALERT_SPACE));
        if (alertThread <= smsTotalTimes && Math.floorMod(smsTotalTimes - alertThread, space) == 0) {
            SmsTool.alertDingDing(WinPublicTool.buildWinString(Constants.Template.TEMP_SMS_ALERT, String.valueOf(smsTotalTimes), String.valueOf(alertThread)), Constants.TUIA_ACTIVITY_DING_TOKEN);
        }
        consumerService.setSmsTotalTimes(++smsTotalTimes);
        return true;
    }

    public void innerLog(ConsumerReq req, UserAccount userAccount, String userId) {
        JSONObject json = new JSONObject();
        json.put("app_id", userAccount.getAppId().toString());
        json.put("slot_id", RequestLocal.get().getSlotId());
        json.put("consumer_id", userId);
        json.put("ip", RequestLocal.get().getIp());
        json.put("mobile_number", req.getPhone());
        InnerLogService.innerJsonObject(InnerLogCode.INNER_GROUP, InnerLogCode.SMS_REQ_TYPE, json);
    }

    @Override
    public Boolean imgCheck(String phone) {
        Long consumerId = RequestLocal.get().getCid();
        String ip = RequestLocal.get().getIp();
        String ipCount = commonService.getSystemConfig(Constants.TuiaKey.TUIA_SMS_IP_TIMES);
        String userAndPhoneCount = commonService.getSystemConfig(Constants.TuiaKey.TUIA_USER_SMS_TIMES);
        RequestLocal.get().getCid();
        int phoneTimes = consumerService.getSmsTimes(PHONE_PREFIX + phone);
        int userTimes = consumerService.getSmsTimes(USER_PREFIX + consumerId);
        int ipTimes = consumerService.getSmsTimes(IP_PREFIX + ip);
        // 如果触发了条件.则需要把该用户加入到yidun检验列表中
        if (phoneTimes >= Integer.parseInt(userAndPhoneCount) || userTimes >= Integer.parseInt(userAndPhoneCount) || ipTimes >= Integer.parseInt(ipCount)) {
            consumerService.setYiDunVerifyList(consumerId.toString());
            return true;
        }
        return consumerService.isYiDunVerifyList(consumerId.toString());
    }

    @Override
    public void updateConsumerInfo(CommonLoginReq req) throws ActivityException {
        UserAccount userAccount = RequestLocal.get().getUserAccount();
        if(userAccount == null || !userAccount.getLoginStatus()){
            throw new ActivityException(ErrorCode.E0200003);
        }
        //确认使用昵称
        consumerService.confirmNickName(req.getNickName());
        ConsumerDto dto = new ConsumerDto();
        dto.setUserId(userAccount.getUserId());
        ConsumerDto.ExtInfo extInfo = new ConsumerDto.ExtInfo();
        extInfo.setSex(req.getSex());
        extInfo.setNickName(req.getNickName());
        extInfo.setImg(req.getImg());
        dto.setExtInfo(extInfo);
        consumerService.updateConsumer(dto);
        consumerService.setConsumerCache(new ConsumerCache(userAccount.getUserId(), userAccount.getAppId(), extInfo.getSex(), extInfo.getNickName(), extInfo.getImg(), extInfo.getLoginType(), userAccount.getPartnerUserId()));
    }

    @Override
    public String getTongDunDeviceId(String tokenId, HttpServletRequest request) {
        //1.请求同盾
        Map<String, String> param = new HashMap<>();
        param.put("ip_address", RequestTool.getIpAddr(request));
        param.put("token_id", tokenId);
        param.put("event_occur_time", new DateTime().toString("yyyy-MM-dd HH:mm:ss"));
        param.put("partner_code", FraudApiRequest.PARTNER_CODE);
        param.put("secret_key", FraudApiRequest.SECRET_KEY);
        param.put("event_id", FraudApiRequest.EVENT_ID);
        param.put("resp_detail_type", FraudApiRequest.RESP_DETAIL_TYPE);
        String resp = JsoupUtil.doPost(FraudApiRequest.API_URL, param);
        //2.设置deviceId，可能没有
        if (StringUtils.isNotBlank(resp)) {
            FraudApiResponse fraudApiResponse = JSONObject.parseObject(resp, FraudApiResponse.class);
            if (fraudApiResponse.getSuccess()) {
                Object deviceId = fraudApiResponse.getDevice_info().get("deviceId");
                if (deviceId == null) {
                    deviceId = "0";
                }
                return String.valueOf(deviceId);
            } else {
                //同盾返回错误码，记录日志
                log.error("获取同盾信息失败,错误信息={}", fraudApiResponse.getReason_code());
            }
        }
        return "0";
    }

    public boolean verify(String userId, String validate) {
        YiDunVerifyReq yiDunVerifyReq = new YiDunVerifyReq();
        yiDunVerifyReq.setValidate(validate);
        yiDunVerifyReq.setUser(userId);
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            yiDunVerifyReq.setSignature(YiDunVerifyReq.genSignature(YiDunVerifyReq.SECRET_KEY, yiDunVerifyReq.setMap()));
            HttpPost httpPost = new HttpPost(YiDunVerifyReq.URL);
            List<NameValuePair> list = HttpRequestTool.getPostParamString(yiDunVerifyReq.setMap());
            list.add(new BasicNameValuePair("signature", yiDunVerifyReq.getSignature()));
            UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, "UTF-8");
            httpPost.setEntity(entity);

            HttpEntity response = httpClient.execute(httpPost).getEntity();
            if (response != null) {
                JSONObject jsonObject = JSON.parseObject(EntityUtils.toString(response, "UTF-8"));
                return jsonObject.getBooleanValue("result");
            }
            log.warn("调用易盾验证码二次验证接口响应失败");
        } catch (IOException e) {
            log.warn("调用易盾验证码二次验证失败", e);
        }
        return false;
    }

}
