package com.github.wxiaoqi.security.admin.rpc.service;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.github.wxiaoqi.security.admin.biz.*;
import com.github.wxiaoqi.security.admin.constant.RedisKey;
import com.github.wxiaoqi.security.admin.constant.enumerate.UserSourceEnum;
import com.github.wxiaoqi.security.admin.dto.BaseUserMemberExportDTO;
import com.github.wxiaoqi.security.admin.dto.RegisterParamDTO;
import com.github.wxiaoqi.security.admin.dto.RegisterQueueDTO;
import com.github.wxiaoqi.security.admin.dto.UserMemberDTO;
import com.github.wxiaoqi.security.admin.entity.*;
import com.github.wxiaoqi.security.admin.vo.AppUserVo;
import com.github.wxiaoqi.security.admin.vo.ImiVo;
import com.github.wxiaoqi.security.api.vo.authority.PermissionInfo;
import com.github.wxiaoqi.security.api.vo.user.AppUserInfo;
import com.github.wxiaoqi.security.common.config.rabbit.RabbitConstant;
import com.github.wxiaoqi.security.common.msg.ObjectRestResponse;
import com.github.wxiaoqi.security.common.util.*;
import com.github.wxiaoqi.security.common.util.process.ResultCode;
import com.github.wxiaoqi.security.common.util.process.SystemConfig;
import com.github.wxiaoqi.security.common.util.result.JsonResultUtil;
import com.upyuns.platform.rs.datacenter.fegin.DatacenterFeign;
import com.upyuns.platform.rs.gtdata.GtDataRestClient;
import com.upyuns.platform.rs.universal.dto.SmsTemplateDTO;
import com.upyuns.platform.rs.universal.feign.MQSenderFeign;
import com.upyuns.platform.rs.universal.feign.RegionFeign;
import com.upyuns.platform.rs.universal.feign.ThirdFeign;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;

import static com.github.wxiaoqi.security.common.config.rabbit.RabbitConstant.KEY_APPUSER_AUTH;
import static com.github.wxiaoqi.security.common.config.rabbit.RabbitConstant.KEY_IMAGE_INPUT_SUCC;

/**
 * @author keliii
 */
@Service
@Transactional
@Slf4j
public class AppPermissionService {

    @Autowired
    AppUserBiz appUserBiz;

    @Autowired
    ElementBiz elementBiz;

    @Autowired
    ThirdFeign thirdFeign;

    @Autowired
    MQSenderFeign mqSenderFeign;

    @Autowired
    DatacenterFeign datacenterFeign;

    @Autowired
    private MyWaterBiz walletBiz;

    private BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(12);
    @Autowired
    private RedisTemplate userRedisTemplate;
    @Autowired
    private AppUserDetailBiz appUserDetailBiz;
    @Autowired
    private AppUserLoginBiz appUserLoginBiz;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private BaseUserMemberExportBiz baseUserMemberExportBiz;

    @Autowired
    private BaseUserMemberBiz baseUserMemberBiz;

//    @Value("${admin.smallName}")
//    private  String  smallName;

    @Autowired
    private  AppUserPhoneNotesBiz notesBiz;

    @Autowired
    private  AppUserAlipayBiz alipayBiz;

    @Autowired
    GtDataRestClient gtDataRestClient;


    private  static final  Integer  maxNumber=5;


    public AppUserInfo validate(String username, String password) {
        AppUserInfo info = new AppUserInfo();
        AppUserLogin user = appUserLoginBiz.checkeUserLogin(username);
        if (user != null && encoder.matches(password, user.getPassword())) {
            info.setUsername(user.getUsername());
            info.setId(user.getId() + "");
        }
        return info;
    }

    public List<PermissionInfo> getPermissionByUsername(String username) {
        AppUser user = appUserBiz.getUserByUsername(username);
        List<PermissionInfo> result = new ArrayList<>();
//        List<Element> elements = elementBiz.getAuthorityElementByUserId(user.getId().toString());
        List<Element> elements = elementBiz.getAuthorityElementByAppUserId(user.getId().toString());
        element2permission(result, elements);
        return result;
    }

    private void element2permission(List<PermissionInfo> result, List<Element> elements) {
        PermissionInfo info;
        for (Element element : elements) {
            info = new PermissionInfo();
            info.setCode(element.getCode());
            info.setType(element.getType());
            info.setUri(element.getUri());
            info.setMethod(element.getMethod());
            info.setName(element.getName());
            info.setMenu(element.getMenuId());
            result.add(info);
        }
    }


    /**
     * 发送短信
     *
     * @param phone
     * @param type
     * @return phone手机号 type:类型(0用户注册,1微信绑定,2人脸注册,3忘记密码,4直接发送验证码) 改写发送验证码方法（暂时通过测试）
     */

    public JSONObject sendSMS(String phone, Integer type, String pointList) {
        if (StringUtils.isBlank(phone) || type == null) {
            return JsonResultUtil.createFailedResult(ResultCode.NULL_CODE, "参数为空");
        }
        // 验证手机号码是否正确
        if (!VerificationUtils.getPvu().checkMobileNumber(phone)) {
            return JsonResultUtil.createFailedResult(ResultCode.FAILED_CODE, "手机号码有误");
        }
        // 组织返回结果集
        JSONObject result = new JSONObject();
        if (type == 0) {// 注册验证码
            AppUserLogin rsUserLogin = appUserLoginBiz.checkeUserLogin(phone);
            if (rsUserLogin != null) {
                return JsonResultUtil.createFailedResult(ResultCode.EXIST_CODE, "用户已存在");
            }
//            ObjectRestResponse<Boolean> objectRestResponse = thirdFeign.verify(phone, pointList);
//                if (objectRestResponse.getData() == null || objectRestResponse.getData() == false) {
//                    return JsonResultUtil.createFailedResult(ResultCode.FAILED_CODE, "图片验证码验证失败");
//                }
        } else if (type == 1) {
            AppUserLogin rsUserLogin = appUserLoginBiz.checkeUserLogin(phone);

            // 判断手机号码是否已绑定
            boolean isBind = appUserLoginBiz.checkeWechatUser(rsUserLogin);
            if (!isBind) {
                return JsonResultUtil.createFailedResultMsg(ResultCode.WX_BIND_CODE);
            } else {
                result.put("registered", rsUserLogin != null);
            }
        }/* else if (type == 3) {
            if (checkeUserLogin(phone) == null)
                return JsonResultUtil.createFailedResult(ResultCode.FAILED_CODE, "手机号未注册，请确认手机号无误");
        }*/ else if (type == 4) {
            AppUserLogin rsUserLogin = appUserLoginBiz.checkeUserLogin(phone);
            if (rsUserLogin == null)
                return JsonResultUtil.createFailedResult(ResultCode.EXIST_CODE, "手机号未注册");
        }
        // String sms = PassportUtil.SendSMS(phone, SystemConfig.SENDSMS_TITLE);
        String mobilecode = null;
        JSONObject data = thirdFeign.send(phone);
        if (data != null && data.getInteger("status") == ResultCode.SUCCESS_CODE) {
            mobilecode = data.getString("data");
        }
        log.info("调用短信发送接口返回值为：{}", mobilecode);
        // 判断返回值是否为空，并且是否可以转换成JSONObject
        if (StringUtils.isBlank(mobilecode)) {
            return JsonResultUtil.createDefaultFail();
        }
        try {
            result.put("mobilecode", "");//mobilecode
            String redisLockKey = RedisKey.CONSTANT_CODE_PREFIX + phone + mobilecode;
            Boolean suc = userRedisTemplate.opsForValue().setIfAbsent(redisLockKey, mobilecode);
            if (suc) {
                userRedisTemplate.expire(redisLockKey, 5, TimeUnit.MINUTES);//5分钟内过期
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return JsonResultUtil.createFailedResult(ResultCode.EXCEPTION_CODE, "出现异常");
        }
        return JsonResultUtil.createSuccessResultWithObj(result);
    }

    //检查验证码是否正确
    public String checkCodeByUsername(String username,String mobilecode){
        // 判断参数和验证码
        if (StringUtils.isBlank(username)  || StringUtils.isBlank(mobilecode)) {
            log.info("---参数为空------");
            return null;
        }
        String redisLockKey = RedisKey.CONSTANT_CODE_PREFIX + username + mobilecode;
        String mobilecodeRedis = userRedisTemplate.opsForValue().get(redisLockKey) == null ? "" : userRedisTemplate.opsForValue().get(redisLockKey).toString();
        log.error("checkCodeByUsername接口，获取redis中的验证码：" + mobilecodeRedis);
        if (StringUtils.isBlank(mobilecodeRedis)) {
            log.info("---验证码错误------username==="+username);
            return null;
        }
        return redisLockKey;
    }

    /**
     * 注册用户
     *
     * @param username
     * @param password
     * @param headimgurl
     * @param mobilecode
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public JSONObject register(String username, String password, String headimgurl,
                               String nickname, String mobilecode, String openId, String unionid, Integer type,String code,Integer channel) {
        log.info("register------code====="+code+"----开始进入方法---time===="+System.currentTimeMillis()/1000L);
        String activityCode = null;
        // 判断参数和验证码
        if (StringUtils.isBlank(username) || StringUtils.isBlank(password) || StringUtils.isBlank(mobilecode)) {
            return JsonResultUtil.createFailedResult(ResultCode.NULL_CODE, "参数为空");
        }
        if (StringUtils.isNotBlank(code)){
            //判断处理活动关键字
            String[] codes = code.split("_");
            if(codes.length > 0) {
                String userCode = codes[0];
                if(appUserDetailBiz.getUserByCode(userCode)==0) {
                    return JsonResultUtil.createFailedResult(ResultCode.NOTEXIST_CODE, "邀请人不存在");
                }
            }
        }
        String redisLockKey = RedisKey.CONSTANT_CODE_PREFIX + username + mobilecode;
        String mobilecodeRedis = userRedisTemplate.opsForValue().get(redisLockKey) == null ? "" : userRedisTemplate.opsForValue().get(redisLockKey).toString();
        log.info("注册接口，获取redis中的验证码：" + mobilecodeRedis+"---time===="+System.currentTimeMillis()/1000L);
        // 获取到缓存的验证码后要先清空缓存对应键的值
        userRedisTemplate.delete(redisLockKey);
        if (StringUtils.isBlank(mobilecodeRedis)) {
            return JsonResultUtil.createFailedResult(ResultCode.NOTEXIST_CODE, "验证码错误");
        }
        return registerCommon(username, password, headimgurl, nickname, openId, unionid, type, code, channel, activityCode);
    }

    public JSONObject registerCommon(String username, String password, String headimgurl, String nickname, String openId, String unionid, Integer type, String code, Integer channel, String activityCode) {
        // 是否已存在
        AppUserLogin user = appUserLoginBiz.checkeUserLogin(username);
        if (null != user) {
            return JsonResultUtil.createFailedResult(ResultCode.EXIST_CODE, "用户已存在");
        }
        // 新增用户登录信息
        try {
            Long now = System.currentTimeMillis() / 1000;
            AppUserLogin appUserLogin = new AppUserLogin();

            appUserLogin.setUsername(username);
            appUserLogin.setPassword(password);
            appUserLogin.setIsdel(0);
            appUserLogin.setStatus(0);
            //QQ
            if (type == 1 && StringUtils.isNotBlank(openId)) {
                appUserLogin.setOpenid(openId);
            } else {
                if (StringUtils.isNotBlank(openId)) {
                    appUserLogin.setWxOpenid(openId);
                }
                if (StringUtils.isNotBlank(unionid)) {
                    appUserLogin.setUnionid(unionid);
                }
            }
            appUserLogin.setCreatetime(now);
            appUserLogin.setUpdatetime(now);
            appUserLoginBiz.insertSelective(appUserLogin);

            //创建data账号
            String gtdataPass = AssertUtils.isFeignSucc(datacenterFeign.dataRegister(appUserLogin.getId())).getData().get("gtdataPass");
            appUserLogin.setGtdataPass(gtdataPass);
            appUserLoginBiz.updateSelectiveById(appUserLogin);

            Integer userid = appUserLogin.getId();
            log.info("注册：新增登陆用户信息： " + userid+"---time===="+System.currentTimeMillis()/1000L);
            // 新增用户详情
            AppUserDetail rsUserDetail = new AppUserDetail();
            rsUserDetail.setUserid(userid);
            rsUserDetail.setNickname(nickname);
            rsUserDetail.setHeadimgurl(headimgurl); // 默认路径，待写
            rsUserDetail.setCreatetime(now);
            rsUserDetail.setUpdatetime(now);
            rsUserDetail.setIsdel(0);
            rsUserDetail.setCrtHost(getIp());

            rsUserDetail.setChannel(channel);
            appUserDetailBiz.insertSelective(rsUserDetail);
            // 登录结果要做做统一处理
            JSONObject data = autoLogin(userid, username, headimgurl, nickname, code, activityCode,1);
            log.info("注册：登录结果要做做统一处理： " + userid+"---time===="+System.currentTimeMillis()/1000L);
            if (data != null) {
                return JsonResultUtil.createSuccessResultWithObj(data);
            } else {
                return JsonResultUtil.createDefaultFail();
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return JsonResultUtil.createFailedResult(ResultCode.EXCEPTION_CODE, "出现异常");
        }
    }


    public  void  test(){
        Example example=new Example(AppUserLogin.class);
        example.createCriteria().andEqualTo("imUserid",0);
        List<AppUserLogin> list=appUserLoginBiz.selectByExample(example);
        for (AppUserLogin userLogin:list) {
            Long now = System.currentTimeMillis() / 1000;
            Integer userId = userLogin.getId();
            String username = userLogin.getUsername();
            String ip = getIp();
            String nickname = SystemConfig.USER_NIKENAME_DEFAULT + (int) ((Math.random() * 9 + 1) * 100000);
            AppUserDetail rsUserDetail = new AppUserDetail();
            rsUserDetail.setUserid(userId);
            rsUserDetail = appUserDetailBiz.selectOne(rsUserDetail);
            if (rsUserDetail == null) {
                rsUserDetail=new AppUserDetail();
                rsUserDetail.setUserid(userId);
                rsUserDetail.setNickname(nickname);
                rsUserDetail.setHeadimgurl(SystemConfig.USER_HEADER_URL_DEFAULT); // 默认路径，待写
                rsUserDetail.setCreatetime(now);
                rsUserDetail.setUpdatetime(now);
                rsUserDetail.setIsdel(0);
                rsUserDetail.setCrtHost(ip);
                //生成邀请码 长度改为8 不然重复率太高
                rsUserDetail.setCode(ReferralCodeUtil.encode(userId));
                appUserDetailBiz.insertSelective(rsUserDetail);
            } else {
                nickname=rsUserDetail.getNickname();
            }
        }

    }

    private void sendQueue(String username, String password, String headimgurl, String nickname, String mobilecode, String openId, String unionid, Integer type, String code, String activityCode, Integer userid,Integer sign) {
        try {
            RegisterQueueDTO registerQueueDTO = new RegisterQueueDTO();
            //出参
//                    registerQueueDTO.setData(data);
            registerQueueDTO.setAppUserId(userid);
            registerQueueDTO.setSign(sign);
            //入参
            registerQueueDTO.setInParamDTO(new RegisterParamDTO(username, password, headimgurl,
                    nickname, mobilecode, openId, unionid, type, code, activityCode));
//                    注册成功，发送队列
            switch (sign){
                case 1 :
                    mqSenderFeign.sendMessage(RabbitConstant.ADMIN_TOPIC, KEY_IMAGE_INPUT_SUCC, JSONUtil.toJsonStr(registerQueueDTO));
                    break;
                case 2 :
                    mqSenderFeign.sendMessage(RabbitConstant.ADMIN_TOPIC, KEY_APPUSER_AUTH, JSONUtil.toJsonStr(registerQueueDTO));
                    break;
                default:
                    break;
            }
        }catch (Exception e){
            log.error(e.getMessage(), e);
        }
    }

    /**
     * 自动登录type;1-app;2-小程序
     */
    public JSONObject autoLogin(Integer userid, String username, String headimgurl, String nickname,String code,String activityCode,Integer type) {
        log.info("-----------autoLogin----code==="+code+"----activityCode===="+activityCode);
        JSONObject data = new JSONObject();
        AppUserVo userVo = appUserDetailBiz.getUserInfoById(userid);
      //  AppUserDetail appUserDetail = appUserDetailBiz.selectById(userVo.getId());
        System.out.println(userVo);
        if (userVo != null) {
            data.put("nickname", nickname);
            data.put("headerurl", headimgurl);
            if (StringUtils.isNotBlank(userVo.getNickname())) {
                data.put("nickname", userVo.getNickname());
            }
            if (StringUtils.isNotBlank(userVo.getHeadimgurl())) {
                data.put("headerurl", userVo.getHeadimgurl());
            }
            data.put("certificationStatus", userVo.getCertificationStatus());
            data.put("username", StringUtils.isNotEmpty(username) ? username : userVo.getUsername());
            data.put("userId", userid);
            data.put("imUserId", userVo.getImUserid());
            data.put("code", userVo.getCode());
            data.put("positionId", userVo.getPositionId());
            data.put("administrators",userVo.getAdminStrators());
            //更新登录时间 和 ip
            String clientIp = getIp();
            appUserLoginBiz.updateLoginInfo(userid, clientIp);
        }
        return data;
    }

    public static String getIp() {
        try {
            ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            return requestAttributes.getRequest().getHeader("userHost");
        }catch (Exception e){
            log.error(e.getMessage(), e);
            return  null;
        }

    }

    /**
     * 微信绑定/注册
     *
     * @param username
     * @param password
     * @param openId
     * @param unionid
     * @param nickname
     * @param headimgurl
     * @param type
     * @param mobilecode
     * @return
     */
    @Transactional
    public JSONObject weCahtRegister(String username, String password, String openId,
                                     String unionid, String nickname, String headimgurl, int type, String mobilecode, Integer isQQ,String code,Integer channel) {
        // 校验参数和验证码
        if (StringUtils.isBlank(username) || StringUtils.isBlank(mobilecode)) {
            return JsonResultUtil.createFailedResult(ResultCode.NULL_CODE, "参数为空");
        }
        if (type == 2) {
            if (StringUtils.isBlank(password)) {
                return JsonResultUtil.createFailedResult(ResultCode.NULL_CODE, "密码不能为空");
            }
        }
        try {
            // 获取缓存用户信息
            log.error("weCahtRegister:" + openId);
            if (StringUtils.isNotBlank(openId)) {
                if (StringUtils.isNotBlank(nickname)) {
                    // 转换特殊字符
                    nickname = EmojiFilter.filterEmoji(nickname);
                }
                log.error("微信昵称=" + nickname);
                // 微信用户未设置头像时，默认头像
                if (StringUtils.isBlank(headimgurl)) {
                    headimgurl = SystemConfig.USER_HEADER_URL_DEFAULT;
                }
                if (type == 1) { // 绑定
                    String redisLockKey = RedisKey.CONSTANT_CODE_PREFIX + username + mobilecode;
                    String mobilecodeRedis = userRedisTemplate.opsForValue().get(redisLockKey) == null ? "" : userRedisTemplate.opsForValue().get(redisLockKey).toString();
                    log.error("注册接口，获取redis中的验证码：" + mobilecodeRedis);
                    // 获取到缓存的验证码后要先清空缓存对应键的值
                    userRedisTemplate.delete(redisLockKey);
                    if (StringUtils.isBlank(mobilecodeRedis)) {

                        return JsonResultUtil.createFailedResult(ResultCode.NOTEXIST_CODE, "验证码错误");
                    }
                    Long now = System.currentTimeMillis() / 1000;
                    AppUserLogin userLogin = appUserLoginBiz.checkeUserLogin(username);
                    if ((isQQ == 1 && StringUtils.isNotBlank(userLogin.getOpenid())) || (isQQ == 0 && StringUtils.isNotBlank(userLogin.getWxOpenid()))) {
                        // 已绑定微信
                        return JsonResultUtil.createFailedResultMsg(ResultCode.WX_BIND_CODE);
                    }
                    Integer userid = userLogin.getId();
                    if (isQQ == 1) {
                        userLogin.setOpenid(openId);
                    } else {
                        userLogin.setWxOpenid(openId);
                        // 添加unionid
                        userLogin.setUnionid(unionid);
                    }
                    userLogin.setUpdatetime(now);
                    appUserLoginBiz.updateSelectiveById(userLogin);
                    AppUserVo userVo = appUserDetailBiz.getUserInfoById(userid);
                    AppUserDetail userDetail = new AppUserDetail();
                    if (userVo == null) {
                        userDetail.setUserid(userid);
                        userDetail.setHeadimgurl(headimgurl);
                        userDetail.setNickname(nickname);
                        userDetail.setCreatetime(now);
                        userDetail.setUpdatetime(now);
                        userDetail.setIsdel(0);
                        userDetail.setCrtHost(getIp());
                        userDetail.setChannel(channel);
                        //setCreateIPInfo(userDetail);
                        appUserDetailBiz.insertSelective(userDetail);

                    } /*else {
                        userDetail.setId(userVo.getId());
                        userDetail.setHeadimgurl(headimgurl);
                        userDetail.setNickname(nickname);
                        appUserDetailBiz.updateSelectiveById(userDetail);
                    }*/
                    String activityCode=null;
                    if (StringUtils.isNotBlank(code)){
                        //判断处理活动关键字
                        String[] codes = code.split("_");
                        if(codes.length > 1) {
                            code = codes[0];
                            activityCode = codes[1];
                        }
                    }
                    // 登录结果要做做统一处理
                    JSONObject data = autoLogin(userid, username, headimgurl, nickname,code,activityCode,1);
                    // 到im登录，获取返回结果
                    /*Integer  imUserId=userLogin.getImUserid();
                    String imPassword=userLogin.getImPassword();
                    if(StringUtils.isNotBlank(imPassword)&&imUserId!=null&&imUserId>0){
                        String  access_token=loginIm(username,imPassword,imUserId);
                        data.put("imToken",access_token);
                        data.put("imUserId",imUserId);
                    }*/
                    if (data != null) {
                        return JsonResultUtil.createSuccessResultWithObj(data);
                    }
                } else if (type == 2) { // 新增
                    JSONObject register = register(username, password, headimgurl, nickname, mobilecode,
                            openId, unionid, isQQ,code,channel);
                    if (register.getInteger("status") != ResultCode.SUCCESS_CODE) {
                        if (register.getInteger("status") == ResultCode.EXIST_CODE) {
                            return JsonResultUtil.createFailedResult(ResultCode.EXIST_CODE, "用户已存在");
                        }
                        if (register.getInteger("status") == ResultCode.NOTEXIST_CODE) {
                            return JsonResultUtil.createFailedResult(ResultCode.NOTEXIST_CODE, register.getString("message"));
                        }
                        return JsonResultUtil.createFailedResult(register.getInteger("status"), "操作失败");
                    }
                    return register;

                }
            }
            return JsonResultUtil.createDefaultFail();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return JsonResultUtil.createFailedResult(ResultCode.EXCEPTION_CODE, "出现异常");
        }

    }


    public  void  setErrorNum(String username){
        String redisLockKey = RedisKey.CONSTANT_ERROR_PREFIX + username;
        Integer number=getErrorNum(username,redisLockKey);
        userRedisTemplate.delete(redisLockKey);
        Boolean suc = userRedisTemplate.opsForValue().setIfAbsent(redisLockKey, number+1);
        if (suc) {
            userRedisTemplate.expire(redisLockKey, 5, TimeUnit.MINUTES);//5分钟内过期
        }
    }
    public  boolean checkErrorNum(String username){
        String redisLockKey = RedisKey.CONSTANT_ERROR_PREFIX + username;
        Integer number=getErrorNum(username,redisLockKey);
        if (number>=maxNumber){
            return  true;
        }
        return  false;
    }
    public  Integer  getErrorNum(String username,String redisLockKey){
        String errorNum = userRedisTemplate.opsForValue().get(redisLockKey) == null ?"0": userRedisTemplate.opsForValue().get(redisLockKey).toString();
        Integer number=0;
        if (StringUtils.isNotBlank(errorNum)){
            number=Integer.parseInt(errorNum);
        }
        return number;
    }


    /**
     * 校验手机号码是否已绑定微信
     *
     * @param username
     * @return
     */

    public JSONObject checkBindWechat(String username,Integer type) {
        JSONObject data = new JSONObject();
        try {
            AppUserLogin userLogin = appUserLoginBiz.checkeUserLogin(username);
            if (userLogin != null) {
                String openid = userLogin.getOpenid();
                if (type==null||type==0){
                    openid=userLogin.getWxOpenid();
                }else if (type==2){
                    List<AppUserAlipay> list=alipayBiz.getListByUserId(userLogin.getId());
                    if (list.size()>0){
                        openid=list.get(0).getTxAlipay();
                    }
                }
                if (StringUtils.isNotBlank(openid)) {
                    data.put("type", 0); // 已存在
                } else {
                    data.put("type", 1); // 绑定
                }
            } else {
                data.put("type", 2); // 新增
            }
            return JsonResultUtil.createSuccessResultWithObj(data);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return JsonResultUtil.createFailedResult(ResultCode.EXCEPTION_CODE, "出现异常");
        }
    }

    /**
     * 微信登录
     *
     * @param openId
     * @return
     */
    @Transactional
    public JSONObject weCahtLogin(String openId, Integer isQQ,String code) {
        if (StringUtils.isBlank(openId)) {
            return JsonResultUtil.createFailedResult(ResultCode.NULL_CODE, "参数为空");
        }
        AppUserLogin userLogin = appUserLoginBiz.getUserByOpenid(openId, isQQ);
        if (userLogin == null) {
            return JsonResultUtil.createFailedResult(ResultCode.WXNOTEXIST_CODE, "该微信号尚未绑定手机号");
        }
        if (userLogin.getStatus() == 1) {
            return JsonResultUtil.createFailedResult(ResultCode.EXIST_CODE, "用户已被禁用");
        }
        Integer userid = userLogin.getId();
        AppUserVo userVo = appUserDetailBiz.getUserInfoById(userid);
        String headimgurl = "";
        String nickname = "";
        if (userVo != null) {
            headimgurl = userVo.getHeadimgurl();
            nickname = userVo.getNickname();
        }
        String activityCode=null;
        if (StringUtils.isNotBlank(code)){
            //判断处理活动关键字
            String[] codes = code.split("_");
            if(codes.length > 1) {
                code = codes[0];
                activityCode = codes[1];
            }
        }
        JSONObject data = autoLogin(userid, userLogin.getUsername(), headimgurl, nickname,code,activityCode,1);
       /* // 到im注册，获取返回结果
        Integer  imUserId=userLogin.getImUserid();
        String imPassword=userLogin.getImPassword();
        if(StringUtils.isNotBlank(imPassword)&&imUserId!=null&&imUserId>0){
            String  access_token=loginIm(userLogin.getUsername(),imPassword,imUserId);
            data.put("imToken",access_token);
            data.put("imUserId",imUserId);
        }*/
        if (data != null) {
            return JsonResultUtil.createSuccessResultWithObj(data);
        }
        return JsonResultUtil.createDefaultFail();
    }

    public JSONObject login(String username, String password, String mobilecode, int type,String code) {
        if (StringUtils.isBlank(username) || ((StringUtils.isBlank(password) && type == 1) || (StringUtils.isBlank(mobilecode) && type == 2))) {
            return JsonResultUtil.createFailedResult(ResultCode.NULL_CODE, "请求参数为空");
        }
        try {
            AppUserLogin user = appUserLoginBiz.checkeUserLogin(username);
            if (type == 1) {
                if (user == null || !encoder.matches(password, user.getPassword()))
                    return JsonResultUtil.createFailedResult(ResultCode.EXIST_CODE, "用户名或密码错误");
            } else {
                String redisLockKey = RedisKey.CONSTANT_CODE_PREFIX + username + mobilecode;
                String mobilecodeRedis = userRedisTemplate.opsForValue().get(redisLockKey) == null ? "" : userRedisTemplate.opsForValue().get(redisLockKey).toString();
                log.error("验证码登录接口，获取redis中的验证码：" + mobilecodeRedis);
                // 获取到缓存的验证码后要先清空缓存对应键的值
                userRedisTemplate.delete(redisLockKey);
                if (StringUtils.isBlank(mobilecodeRedis))
                    return JsonResultUtil.createFailedResult(ResultCode.NOTEXIST_CODE, "验证码错误");
                if (user == null)
                    return JsonResultUtil.createFailedResult(ResultCode.NOTEXIST_CODE, "用户不存在");

            }
            // 判断是否禁用
            if (user.getStatus() == 1) {
                return JsonResultUtil.createFailedResult(ResultCode.EXIST_CODE, "用户已被禁用");
            }
            Integer userid = user.getId();
            String nickname = SystemConfig.USER_NIKENAME_DEFAULT + (int) ((Math.random() * 9 + 1) * 100000);
            String activityCode=null;

            JSONObject data = autoLogin(userid, user.getUsername(), SystemConfig.USER_HEADER_URL_DEFAULT, nickname,code,activityCode,1);
            if (data != null) {
                return JsonResultUtil.createSuccessResultWithObj(data);
            }
            return JsonResultUtil.createDefaultFail();
        } catch (Exception e) {
            log.error("userlogin->error:{}", e.getMessage(), e);
            return JsonResultUtil.createFailedResult(ResultCode.EXCEPTION_CODE, "出现异常");
        }
    }

    @Transactional
    public JSONObject reset(String username, String mobilecode, String password) {
        if (StringUtils.isBlank(username) || StringUtils.isBlank(mobilecode) || StringUtils.isBlank(password)) {
            return JsonResultUtil.createFailedResult(ResultCode.NULL_CODE, "请求参数为空");
        }
        try {
            String redisLockKey = RedisKey.CONSTANT_CODE_PREFIX + username + mobilecode;
            String mobilecodeRedis = userRedisTemplate.opsForValue().get(redisLockKey) == null ? "" : userRedisTemplate.opsForValue().get(redisLockKey).toString();
            log.error("验证码登录接口，获取redis中的验证码：" + mobilecodeRedis);
            // 获取到缓存的验证码后要先清空缓存对应键的值
            userRedisTemplate.delete(redisLockKey);
            if (StringUtils.isBlank(mobilecodeRedis)) {
                return JsonResultUtil.createFailedResult(ResultCode.NOTEXIST_CODE, "验证码错误");
            }
            AppUserLogin user = appUserLoginBiz.checkeUserLogin(username);
            if (user == null) {
                return JsonResultUtil.createFailedResult(ResultCode.NOTEXIST_CODE, "用户不存在");
            }
            user.setPassword(password);
            appUserLoginBiz.updatePasswordById(user);
            Integer userid = user.getId();
            String nickname = SystemConfig.USER_NIKENAME_DEFAULT + (int) ((Math.random() * 9 + 1) * 100000);
            JSONObject data = autoLogin(userid, user.getUsername(), SystemConfig.USER_HEADER_URL_DEFAULT, nickname,null,null,null);
           /* // 到im登录，获取返回结果
            Integer  imUserId=user.getImUserid();
            String imPassword=user.getImPassword();
            if(StringUtils.isNotBlank(imPassword)&&imUserId!=null&&imUserId>0){
                String  access_token=loginIm(username,imPassword,imUserId);
                data.put("imToken",access_token);
                data.put("imUserId",imUserId);
            }*/
            if (data != null) {
                return JsonResultUtil.createSuccessResultWithObj(data);
            }
            return JsonResultUtil.createDefaultFail();
        } catch (Exception e) {
            log.error("userlogin->error:{}", e.getMessage(), e);
            return JsonResultUtil.createFailedResult(ResultCode.EXCEPTION_CODE, "出现异常");
        }
    }

    //实名认证

    public ObjectRestResponse upAuthentication(Integer userid, String name, String idNumber, Integer status) {
        log.error("userid====" + userid + "-----name====" + name + "----idNumber===" + idNumber + "---status===" + status);
        if (userid == null || userid == 0 || (status == 1 && StringUtils.isBlank(idNumber) && StringUtils.isBlank(name))) {
            return ObjectRestResponse.createFailedResult(ResultCode.NULL_CODE, "参数为空");
        }
        try {
            AppUserVo userVo = appUserDetailBiz.getUserInfoById(userid);
            if (userVo == null) {
                return ObjectRestResponse.createFailedResult(ResultCode.NOTEXIST_CODE, "用户不存在");
            }
            if (userVo.getCertificationStatus() == 1) {
                return ObjectRestResponse.createFailedResultWithObj(ResultCode.EXIST_CODE, "用户已认证", userVo.getIdNumber());
            }
            if (status == 1) {
                String username = userVo.getUsername();
                AppUserLogin user = new AppUserLogin();
                user.setId(userid);
                user.setUsername(username);
                user.setIdNumber(idNumber);
                user.setCertificationStatus(1);
                appUserLoginBiz.updateSelectiveById(user);
                if (StringUtils.isBlank(userVo.getRealname())) {
                    Integer id = userVo.getId();
                    userVo = new AppUserVo();
                    userVo.setId(id);
                    userVo.setUserid(userid);
                    userVo.setRealname(name);
                    appUserDetailBiz.updUuserInfoById(userVo);
                }

            }
            return ObjectRestResponse.succ();
        } catch (Exception e) {
            log.error("upAuthentication->error:{}", e.getMessage(), e);
            return ObjectRestResponse.createFailedResult(ResultCode.EXCEPTION_CODE, "出现异常");
        }

    }

    /**
     * 通过用户id登录*** Unbelievable! ! !
     *
     * @param uid
     * @return
     */
    public JSONObject appletLoginByUserId(Integer uid) {
        JSONObject data = autoLogin(uid, null, null, null,null,null,2);
        if (data.getDate("userId") != null) {
            return JsonResultUtil.createSuccessResultWithObj(data);
        }
        return JsonResultUtil.createFailedResult(ResultCode.NOTEXIST_CODE, "用户不存在");
    }


//    /**
//     * 小程序注册用户
//     *
//     * @param username
//     * @param password
//     * @param headimgurl
//     * @param nickname
//     */
//    @Transactional
//    public JSONObject applyRegister(String username, String password, String headimgurl, String nickname, Integer small_id) {
//        // 判断参数
//        if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) {
//            return JsonResultUtil.createFailedResult(ResultCode.NULL_CODE, "参数为空");
//        }
////        if (StringUtils.isNotBlank(username)){
////            return JsonResultUtil.createFailedResult(ResultCode.FAILED_CODE, "服务升级中，暂不支持注册");
////        }
//        // 是否已存在
//        AppUserLogin user = appUserLoginBiz.checkeUserLogin(username);
//        if (null != user) {
//            return JsonResultUtil.createFailedResult(ResultCode.EXIST_CODE, "用户已存在");
//        }
//        // 新增用户登录信息
//        try {
//            Long now = System.currentTimeMillis() / 1000;
//            AppUserLogin appUserLogin = new AppUserLogin();
//            appUserLogin.setUsername(username);
//            appUserLogin.setPassword(password);
//            appUserLogin.setIsdel(0);
//            appUserLogin.setStatus(0);
//            appUserLogin.setCreatetime(now);
//            appUserLogin.setUpdatetime(now);
//            appUserLoginBiz.insertSelective(appUserLogin);
//            Integer userid = appUserLogin.getId();
//            log.error("注册：新增登陆用户信息： " + userid);
//            // 新增用户详情
//            AppUserDetail rsUserDetail = new AppUserDetail();
//            rsUserDetail.setUserid(userid);
//            rsUserDetail.setNickname(nickname);
//            rsUserDetail.setHeadimgurl(headimgurl); // 默认路径，待写
//            rsUserDetail.setCreatetime(now);
//            rsUserDetail.setUpdatetime(now);
//            rsUserDetail.setIsdel(0);
//            //生成邀请码 长度改为8 不然重复率太高
//            rsUserDetail.setCode(ReferralCodeUtil.encode(userid));
//            //设置来源
//            log.info("register------username====="+username+"----channel===="+UserSourceEnum.APPLET.getCode());
//            rsUserDetail.setChannel(-1);
//            rsUserDetail.setCrtHost(getIp());
//            //setCreateIPInfo(rsUserDetail);
//            rsUserDetail.setState(1);
//            appUserDetailBiz.insertSelective(rsUserDetail);
//            log.error("注册：新增用户详情： " + userid);
//            //创建钱包
//            walletBiz.createWalletByUserId(appUserLogin.getId());
//
//            //上线绑定
//            relationBiz.bindByUserId(userid, small_id);
//            //发送短信通知用户
//            List<String> smsParams = new ArrayList<String>();
//            smsParams.add(smallName);
//            smsParams.add(username);
//            smsParams.add(password);
//            thirdFeign.sendTemplate(new SmsTemplateDTO(){{
//                setPhoneNumbers(username);
//                setType(SmsTemplateDTO.PWD);
//                setParams(smsParams.toArray(new String[smsParams.size()]));
//            }});
//
//            // 登录结果要做做统一处理
//            JSONObject data = autoLogin(userid, username, headimgurl, nickname,null,null,2);
//
//            if (data != null) {
//                return JsonResultUtil.createSuccessResultWithObj(data);
//            } else {
//                return JsonResultUtil.createDefaultFail();
//            }
//        } catch (Exception e) {
//            log.error(e.getMessage(), e);
//            return JsonResultUtil.createFailedResult(ResultCode.EXCEPTION_CODE, "出现异常");
//        }
//    }


//    /**
//     * 通过小程序注册
//     *
//     * @param username
//     * @return
//     */
//    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
//    public JSONObject appletRegistry(String username, String headimgurl, String nickname, Integer small_id) {
//
//        try {
//            // 是否已存在
//            AppUserLogin user = appUserLoginBiz.checkeUserLogin(username);
//            JSONObject data = new JSONObject();
//            if (null == user) {
//                //随机生成密码
//                String password = UUIDUtils.genCodes(8);
//                data = applyRegister(username, password, headimgurl, nickname, small_id);
//            } else {
//                Integer userid = user.getId();
//                //上线绑定
//                relationBiz.bindByUserId(userid, small_id);
//                //登录
//                data = appletLoginByUserId(userid);
//            }
//            return data;
//        } catch (Exception e) {
//            log.error(e.getMessage(), e);
//            return JsonResultUtil.createFailedResult(ResultCode.EXCEPTION_CODE, "出现异常");
//        }
//    }


    public ImiVo findUserInoByImiId(Integer imiId) {
        ImiVo imiVo = new ImiVo();
        AppUserLogin appUserLogin= appUserLoginBiz.findUserByImiId(imiId);
        if (appUserLogin==null){
            return imiVo;
        }
        Map<Integer, AppUserDetail> userIdAndAppUserDetail = appUserDetailBiz.findUserIdAndUserDetailMapByMemberIds(Arrays.asList(appUserLogin.getId()));
        AppUserDetail appUserDetail = userIdAndAppUserDetail.get(appUserLogin.getId());
        if (appUserDetail != null) {
            imiVo.setNickname(appUserDetail.getNickname());
            imiVo.setHeadimgurl(appUserDetail.getHeadimgurl());
        }
        return imiVo;
    }

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void insertUserMemberByUserIdAndPhone(Integer userId, String phone) throws Exception {
        List<BaseUserMemberExportDTO> memberExportDTOS = baseUserMemberExportBiz.findUserMemberExportDataByPhoneAndHashEffective(phone);
        if (CollectionUtils.isNotEmpty(memberExportDTOS)) {
            insertUserMemberByExistUserMemberExportData(userId, memberExportDTOS);
            baseUserMemberExportBiz.updateUserMemberExportDataToLoseEfficacyByPhone(phone,userId);
        }
    }

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public BaseUserMemberExportDTO  findUserMemberByUserIdAndPhone(String phone) throws Exception {
        List<BaseUserMemberExportDTO> memberExportDTOS = baseUserMemberExportBiz.findUserMemberExportDataByPhoneAndHashEffective(phone);
        if (CollectionUtils.isNotEmpty(memberExportDTOS)) {
               return memberExportDTOS.get(0);
        }
        return  null;
    }


    private void insertUserMemberByExistUserMemberExportData(Integer userId, List<BaseUserMemberExportDTO> userMemberExportDTOS) throws Exception {
        UserMemberDTO userMemberDTO;
        for (BaseUserMemberExportDTO userMemberExportDTO : userMemberExportDTOS) {
            userMemberDTO = new UserMemberDTO();
            userMemberDTO.setUserId(userId);
            userMemberDTO.setRentFreeDays(userMemberExportDTO.getRentFreeDays());
            userMemberDTO.setMemberLevel(userMemberExportDTO.getMemberLevel());
            userMemberDTO.setTotalNumber(userMemberExportDTO.getTotalNumber());
            userMemberDTO.setDiscount(userMemberExportDTO.getDiscount());
            userMemberDTO.setBuyCount(0);
            userMemberDTO.setIsBind(1);
            baseUserMemberBiz.updUserMemberByUserId(userMemberDTO);
        }
    }

    //修改手机号码
    public  ObjectRestResponse  updUsername(Integer userId,String username,String mobileCode){
        if (StringUtils.isBlank(username)||StringUtils.isBlank(mobileCode)||userId==0||userId==null){
            return  ObjectRestResponse.createFailedResult(ResultCode.NULL_CODE,"参数不能为空");
        }
        if (StringUtils.isBlank(checkCodeByUsername(username,mobileCode))){
            return  ObjectRestResponse.createFailedResult(ResultCode.FAILED_CODE,"验证码错误");
        }
        log.info("----updUsername----userId==="+userId+"---username==="+username);
        // 是否已存在
        AppUserLogin user = appUserLoginBiz.checkeUserLogin(username);
        if (null != user) {
            return ObjectRestResponse.createFailedResult(ResultCode.EXIST_CODE, "手机号已存在");
        }
        user=appUserLoginBiz.selectById(userId);
        if (user==null){
            return ObjectRestResponse.createFailedResult(ResultCode.EXIST_CODE, "用户不存在");
        }
        AppUserLogin userLogin=new AppUserLogin();
        userLogin.setId(userId);
        userLogin.setUsername(username);
        appUserLoginBiz.disable(userLogin);
        AppUserPhoneNotes notes=new AppUserPhoneNotes();
        notes.setUserId(userId);
        notes.setNewPhone(username);
        notes.setOldPhone(user.getUsername());
        notesBiz.insertSelective(notes);
        return  ObjectRestResponse.succ();

    }


    /**
     * 注册用户
     *
     * @param username
     * @param password
     * @param headimgurl
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public JSONObject adminRegister(String username, String password, String headimgurl,
                               String nickname,String code,Integer channel)throws Exception {
        log.info("register------code====="+code+"----开始进入方法---time===="+System.currentTimeMillis()/1000L);
        String activityCode = null;
        if (StringUtils.isNotBlank(code)){
            //判断处理活动关键字
            String[] codes = code.split("_");
            if(codes.length > 0) {
                String userCode = codes[0];
                if(appUserDetailBiz.getUserByCode(userCode)==0) {
                    return JsonResultUtil.createFailedResult(ResultCode.NOTEXIST_CODE, "邀请人不存在");
                }
            }
        }
        // 是否已存在
        AppUserLogin user = appUserLoginBiz.checkeUserLogin(username);
        if (null != user) {
            return JsonResultUtil.createFailedResult(ResultCode.EXIST_CODE, "用户已存在");
        }
        BaseUserMemberExportDTO exportDTO=findUserMemberByUserIdAndPhone(username);
        if (exportDTO == null){
            return JsonResultUtil.createFailedResult(ResultCode.EXIST_CODE, "不是临时会员");
        }
        // 新增用户登录信息
        try {
            Long now=exportDTO.getCrtTime()/1000L;
            AppUserLogin appUserLogin = new AppUserLogin();
            appUserLogin.setUsername(username);
            appUserLogin.setPassword(password);
            appUserLogin.setIsdel(0);
            appUserLogin.setStatus(0);
            appUserLogin.setCreatetime(now);
            appUserLogin.setUpdatetime(now);
            appUserLoginBiz.insertSelective(appUserLogin);
            Integer userid = appUserLogin.getId();
            log.info("注册：新增登陆用户信息： " + userid+"---time===="+System.currentTimeMillis()/1000L);
            // 新增用户详情
            AppUserDetail rsUserDetail = new AppUserDetail();
            rsUserDetail.setUserid(userid);
            rsUserDetail.setNickname(nickname);
            rsUserDetail.setHeadimgurl(headimgurl); // 默认路径，待写
            rsUserDetail.setCreatetime(now);
            rsUserDetail.setUpdatetime(now);
            rsUserDetail.setIsdel(0);
            rsUserDetail.setCrtHost(getIp());

            //setCreateIPInfo(rsUserDetail);
            log.info("注册：解析地址后： " + userid+"---time===="+System.currentTimeMillis()/1000L);
            //邀请人id关系绑定
            Integer parentId=0;
            //生成邀请码 长度改为8 不然重复率太高
            rsUserDetail.setCode(ReferralCodeUtil.encode(userid));
            rsUserDetail.setChannel(channel);
            appUserDetailBiz.insertSelective(rsUserDetail);
            log.info("注册：新增用户详情： " + userid+"---time===="+System.currentTimeMillis()/1000L);
           /* //绑定上下线关系
            if(parentId!=null&&parentId>0){
                relationBiz.bindRelation(userid,parentId,1);
            }*/
            //临时会员绑定
            insertUserMemberByUserIdAndPhone(userid, username);
            log.info("注册：临时会员绑定： " + userid+"---time===="+System.currentTimeMillis()/1000L);
            log.info("注册：参加新人活动： " + userid+"---time===="+System.currentTimeMillis()/1000L);
            //创建钱包
            walletBiz.createWalletByUserId(appUserLogin.getId());
            log.info("注册：创建钱包： " + userid+"---time===="+System.currentTimeMillis()/1000L);
            // 登录结果要做做统一处理
            JSONObject data = autoLogin(userid, username, headimgurl, nickname,code,activityCode,1);

            log.info("注册：处理im账号： " + userid+"---time===="+System.currentTimeMillis()/1000L);

            //注册gtdata账号
            String gtdataPass = MD5.GetMD5StringLower(appUserLogin.getId().toString());
            Map<String, Object> result = gtDataRestClient.register(appUserLogin.getId()+"", MD5.GetMD5StringLower(gtdataPass), (1024L* 1024L* 1024L* 100)+ "");
            appUserLoginBiz.updateSelectiveById(new AppUserLogin(){{
                setId(appUserLogin.getId());
                setGtdataPass(gtdataPass);
            }});
            if (data != null) {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("userId", userid);
                jsonObject.put("integralRuleCode", "REGISTER");
                //log.info("注册成功获取积分：发送消息 exchange = {}, routingKey = {}, json = {}", RabbitConstant.INTEGRAL_TOPIC, RabbitConstant.INTEGRAL_ROUTING_KEY, jsonObject.toJSONString());
                //mqSenderFeign.sendMessage(RabbitConstant.INTEGRAL_TOPIC, RabbitConstant.INTEGRAL_ROUTING_KEY, jsonObject.toJSONString());
                sendQueue(username, password, headimgurl, nickname, null, null, null, 0, code, activityCode, userid,RegisterQueueDTO.SIGN_NEW);
                log.info("注册：发消息队列： " + userid+"---time===="+System.currentTimeMillis()/1000L);
                return JsonResultUtil.createSuccessResultWithObj(data);
            } else {
                return JsonResultUtil.createDefaultFail();
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return JsonResultUtil.createFailedResult(ResultCode.EXCEPTION_CODE, "出现异常");
        }
    }

}
