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

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.AppUser;
import com.github.wxiaoqi.security.admin.entity.AppUserDetail;
import com.github.wxiaoqi.security.admin.entity.AppUserLogin;
import com.github.wxiaoqi.security.admin.entity.Element;
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.BaseResponse;
import com.github.wxiaoqi.security.common.msg.ObjectRestResponse;
import com.github.wxiaoqi.security.common.util.EmojiFilter;
import com.github.wxiaoqi.security.common.util.ReferralCodeUtil;
import com.github.wxiaoqi.security.common.util.UUIDUtils;
import com.github.wxiaoqi.security.common.util.VerificationUtils;
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.xxfc.platform.activity.feign.ActivityFeign;
import com.xxfc.platform.im.feign.ImFeign;
import com.xxfc.platform.universal.dto.RegionDTO;
import com.xxfc.platform.universal.dto.SmsTemplateDTO;
import com.xxfc.platform.universal.feign.MQSenderFeign;
import com.xxfc.platform.universal.feign.RegionFeign;
import com.xxfc.platform.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 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_APPUSER_REGISTER;

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

    @Autowired
    AppUserBiz appUserBiz;

    @Autowired
    ElementBiz elementBiz;

    @Autowired
    ThirdFeign thirdFeign;

    @Autowired
    MQSenderFeign mqSenderFeign;

    @Autowired
    ImFeign imFeign;

    @Autowired
    ActivityFeign activityFeign;

    @Autowired
    AppUserRelationBiz relationBiz;

    @Resource
    private RegionFeign regionFeign;

    @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;


    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) {
        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, "用户已存在");
            }
        } 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) {
            e.printStackTrace();
            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) {
        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, "参数为空");
        }
        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, "验证码错误");
        }
        // 是否已存在
        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);
            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;
            if (StringUtils.isNotBlank(code)){
                //判断处理活动关键字
                String[] codes = code.split("_");
                if(codes.length > 1) {
                    code = codes[0];
                    activityCode = codes[1];
                }
                parentId=appUserDetailBiz.getUserByCode(code);
            }
            if(parentId!=null&&parentId>0){
                relationBiz.bindRelation(userid, parentId, 1);
                if(StringUtils.isNotBlank(activityCode)){
                    rsUserDetail.setInviterAccount(parentId);
                }

            }
            //生成邀请码 长度改为8 不然重复率太高
            rsUserDetail.setCode(ReferralCodeUtil.encode(userid));
            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);
            //参加新人活动
            jionActivity(userid);
            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("注册：登录结果要做做统一处理： " + userid+"---time===="+System.currentTimeMillis()/1000L);
            // 到im注册，获取返回结果
            Map<String, Object> map = registerIm(username, appUserLogin.getPassword(), nickname);
            log.info("注册：到im注册： " + userid+"---time===="+System.currentTimeMillis()/1000L);
            if (map != null) {
                Integer imUserId = Integer.parseInt(map.get("userId").toString());
                //String access_token=map.get("access_token").toString();
                String imPassword = map.get("password").toString();
                if (imUserId != null && imUserId > 0 && StringUtils.isNotBlank(imPassword)) {
                    AppUserLogin userLogin = new AppUserLogin();
                    userLogin.setId(userid);
                    userLogin.setImPassword(imPassword);
                    userLogin.setImUserid(imUserId);
                    userLogin.setUsername(username);
                    appUserLoginBiz.updateSelectiveById(userLogin);
                    log.info(username + "----userLogin updateSelectiveById---username=====" + username + "----imPassword====" + imPassword);
                }
                //data.put("imToken",access_token);
                data.put("imUserId", imUserId);
            }
            log.info("注册：处理im账号： " + userid+"---time===="+System.currentTimeMillis()/1000L);
            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, mobilecode, openId, unionid, type, code, activityCode, userid,RegisterQueueDTO.SIGN_NEW);
                log.info("注册：发消息队列： " + userid+"---time===="+System.currentTimeMillis()/1000L);
                return JsonResultUtil.createSuccessResultWithObj(data);
            } else {
                return JsonResultUtil.createDefaultFail();
            }
        } catch (Exception e) {
            e.printStackTrace();
            return JsonResultUtil.createFailedResult(ResultCode.EXCEPTION_CODE, "出现异常");
        }
    }

    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_APPUSER_REGISTER, 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);
        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());
            // 缓存操作
            String token = "";
            String imtoken_ = "";
            //userRedisTemplate.opsForValue().set("token_" + userid,token, SystemConfig.REDISTOKENTIME, TimeUnit.SECONDS);
            //userRedisTemplate.opsForValue().set("imtoken_" + userid,imtoken_,SystemConfig.REDISTOKENTIME, TimeUnit.SECONDS);
            // 返回结果
            // data.put("token", token);
            data.put("username", StringUtils.isNotEmpty(username) ? username : userVo.getUsername());
            data.put("userId", userid);
            data.put("imUserId", userVo.getImUserid());
            data.put("code", userVo.getCode());
            //更新登录时间 和 ip
            String clientIp = getIp();
            appUserLoginBiz.updateLoginInfo(userid, clientIp);
            log.info("-----------autoLogin----type==="+type);
            if(type!=null&&type==1){
                try {
                    Integer parentId=0;
                    if (StringUtils.isNotBlank(code)) {
                        parentId = appUserDetailBiz.getUserByCode(code);
                    }
                    //绑定上下线关系
                    if (parentId != null && parentId > 0) {
                        relationBiz.bindRelation(userid, parentId, 1);
                    }
                    //活动消息
                    Integer state=userVo.getState();
                    log.info("-----------autoLogin----state==="+state);
                    if(state!=null&&state==1){
                        if(userVo.getInviterAccount()==null||userVo.getInviterAccount()==0){
                            userVo.setInviterAccount(parentId);
                        }
                        userVo.setState(2);
                        appUserDetailBiz.updUuserInfoById(userVo);
                        sendQueue(username,null, headimgurl, nickname, null, null, null, null, code, activityCode, userid,RegisterQueueDTO.SIGN_ACTIVATE);
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }


        return data;
    }

    public static String getIp() {
        try {
            ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            return requestAttributes.getRequest().getHeader("userHost");
        }catch (Exception e){
            e.printStackTrace();
            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) {
        // 校验参数和验证码
        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());
                        //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);
                    if (register.getInteger("status") != ResultCode.SUCCESS_CODE) {
                        if (register.getInteger("status") == ResultCode.EXIST_CODE) {
                            return JsonResultUtil.createFailedResult(ResultCode.EXIST_CODE, "用户已存在");
                        }
                        return JsonResultUtil.createFailedResult(register.getInteger("code"), "操作失败");
                    }
                    return register;

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

    }

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

    public JSONObject checkBindWechat(String username) {
        JSONObject data = new JSONObject();
        try {
            AppUserLogin userLogin = appUserLoginBiz.checkeUserLogin(username);
            if (userLogin != null) {
                String openid = userLogin.getOpenid();
                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) {
            e.printStackTrace();
            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;
            if (StringUtils.isNotBlank(code)){
                //判断处理活动关键字
                String[] codes = code.split("_");
                if(codes.length > 1) {
                    code = codes[0];
                    activityCode = codes[1];
                }
            }
            JSONObject data = autoLogin(userid, user.getUsername(), SystemConfig.USER_HEADER_URL_DEFAULT, nickname,code,activityCode,1);
            /*// 到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, "出现异常");
        }
    }

    @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, "出现异常");
        }

    }

    //注册im
    public Map<String, Object> registerIm(String username, String password, String nickname) {
        log.error("------注册registerIm----username=====" + username + "-----password===" + password + "---nickname===" + nickname);
        Map<String, Object> map = new HashMap<>();
        map.put("telephone", username);
        map.put("password", password);
        map.put("nickname", nickname);
        BaseResponse response = imFeign.register(map);
        log.error("registerIm->response:{}", response);
        if (response.getStatus() == ResultCode.SUCCESS_CODE) {
            String result = response.getMessage();
            log.error("------im注册----result======" + result);
            if (StringUtils.isNotBlank(result)) {
                JSONObject object = JSONObject.parseObject(result);
                password = object.getString("password");
                if (StringUtils.isNotBlank(result)) {
                    map.put("password", password);
                }
                JSONObject data = object.getJSONObject("data");
                log.error("------im注册----data======" + data);
                if (data != null) {
                    map.put("userId", data.getString("userId"));
                    // map.put("access_token", data.getString("access_token"));
                } else {
                    map.put("userId", "");
                    // map.put("access_token", "");
                }
            }
        }
        return map;

    }

    public String loginImiWithUserId(Integer userId){
        AppUserLogin appUserLogin = appUserLoginBiz.getUserById(userId);
        String token = loginIm(appUserLogin.getUsername(), appUserLogin.getImPassword(), appUserLogin.getImUserid());
        return token;
    }

    //登录im

    public String loginIm(String username, String password, Integer userId) {
        log.error("------登录loginIm----username=====" + username + "-----password===" + password + "---userId===" + userId);
        Map<String, Object> map = new HashMap<>();
        map.put("telephone", username);
        map.put("password", password);
        map.put("userId", userId);
        BaseResponse response = imFeign.login(map);
        log.error("loginIm->response:{}", response);
        String access_token = "";
        if (response.getStatus() == ResultCode.SUCCESS_CODE) {
            String result = response.getMessage();
            log.error("------im登录----result======" + result);
            if (StringUtils.isNotBlank(result)) {
                JSONObject object = JSONObject.parseObject(result);
                JSONObject data = object.getJSONObject("data");
                log.error("------im登录----data======" + data);
                if (data != null) {
                    access_token = data.getString("access_token");
                }
            }
        }
        log.error("------im登录----access_token======" + access_token);
        return access_token;
    }

    //自动领取新人优惠卷
    public String authCoupn(Integer userId) {
        try {
            return activityFeign.led(userId);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    //注册参与活动
    public void jionActivity(Integer userId) {
        try {
             activityFeign.join(userId);
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }
    }


    /**
     * 通过用户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, "参数为空");
        }
        // 是否已存在
        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));
            //设置来源
            rsUserDetail.setChannel(UserSourceEnum.APPLET.getCode());
            rsUserDetail.setCrtHost(getIp());
            //setCreateIPInfo(rsUserDetail);
            rsUserDetail.setState(1);
            appUserDetailBiz.insertSelective(rsUserDetail);
            log.error("注册：新增用户详情： " + userid);
            //创建钱包
            walletBiz.createWalletByUserId(appUserLogin.getId());
            //临时会员绑定
            insertUserMemberByUserIdAndPhone(userid, username);
            //上线绑定
            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()]));
            }});
           //参加新人活动
            jionActivity(userid);
            // 登录结果要做做统一处理
            JSONObject data = autoLogin(userid, username, headimgurl, nickname,null,null,2);
            // 到im注册，获取返回结果
            Map<String, Object> map = registerIm(username, appUserLogin.getPassword(), nickname);
            if (map != null) {
                Integer imUserId = Integer.parseInt(map.get("userId").toString());
                //String access_token=map.get("access_token").toString();
                String imPassword = map.get("password").toString();
                if (imUserId != null && imUserId > 0 && StringUtils.isNotBlank(imPassword)) {
                    AppUserLogin userLogin = new AppUserLogin();
                    userLogin.setId(userid);
                    userLogin.setImPassword(imPassword);
                    userLogin.setImUserid(imUserId);
                    userLogin.setUsername(username);
                    appUserLoginBiz.updateSelectiveById(userLogin);
                    log.info(username + "----userLogin updateSelectiveById---username=====" + username + "----imPassword====" + imPassword);
                }
                //data.put("imToken",access_token);
                data.put("imUserId", imUserId);
            }
            if (data != null) {
                return JsonResultUtil.createSuccessResultWithObj(data);
            } else {
                return JsonResultUtil.createDefaultFail();
            }
        } catch (Exception e) {
            e.printStackTrace();
            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) {
            e.printStackTrace();
            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);
        }
    }


    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);
        }
    }

    /**
     * ip地址 信息解析
     *
     * @param appUserDetail
     */
    public void setCreateIPInfo(AppUserDetail appUserDetail) {
        String crtHost = appUserDetail.getCrtHost();
        if (log.isDebugEnabled()) {
            log.debug("解析的地址：【{}】", crtHost+"---time==="+System.currentTimeMillis()/1000L);
        }
        try {
            analyticalIPByWebSiteAndIPAddress(IPAddress.BASE_IP_PARSING_URL2, crtHost, appUserDetail);
        } catch (Exception e) {
            try {
                analyticalIPByWebSiteAndIPAddress(IPAddress.BASE_IP_PARSING_URL1, crtHost, appUserDetail);
            } catch (Exception ex) {
                log.error("解析地址失败：【{}】", ex.getMessage());
            }

        }

    }

    private void analyticalIPByWebSiteAndIPAddress(String url, String crtHost, AppUserDetail appUserDetail) {
        String ipAddress = restTemplate.getForObject(String.format("%s%s", url, crtHost), String.class);
            log.debug("解析的调用网站后：【{}】", crtHost+"---time==="+System.currentTimeMillis()/1000L);
            String data = JSONObject.parseObject(ipAddress).getString(IPAddress.BASE_DATA);
            JSONObject ipJsonObject = JSONObject.parseObject(data);
            String cityName = ipJsonObject.getString(IPAddress.CITY_NAME);
            RegionDTO regionDTO = regionFeign.getRegionByCityName(StringUtils.isEmpty(cityName) ? "东莞" : cityName);
            log.debug("解析的调用服务后：【{}】", crtHost+"---time==="+System.currentTimeMillis()/1000L);
            if (null != regionDTO) {
                appUserDetail.setProvinceCode(Integer.valueOf(String.valueOf(regionDTO.getParentId())));
                appUserDetail.setCityCode(Integer.valueOf(String.valueOf(regionDTO.getId())));
        }
    }

    /**
     * @author libin
     * @version 1.0.0
     * @dec ip 解析返回的地址信息
     */
    private static class IPAddress {
        public static final String BASE_IP_PARSING_URL1 = "http://ip.taobao.com/service/getIpInfo.php?ip=";
        public static final String BASE_IP_PARSING_URL2 = "https://www.mxnzp.com/api/ip/aim_ip?ip=";
        public static final String BASE_DATA = "data";
        public static final String CITY_NAME = "city";
    }

}
