package com.iformall.controller;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
import cn.binarywang.wx.miniapp.util.crypt.WxMaCryptUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.iformall.annotation.AuthIgnore;
import com.iformall.common.ErrorCode;
import com.iformall.common.Result;
import com.iformall.common.ResultData;
import com.iformall.domain.po.*;
import com.iformall.domain.vo.WxCUserVo;
import com.iformall.domain.vo.WxLevelMerchantCVo;
import com.iformall.enums.EnumAssignTagsTrigger;
import com.iformall.enums.EnumLevelConfigDiscountStatus;
import com.iformall.enums.EnumScoreType;
import com.iformall.enums.EnumUserType;
import com.iformall.service.*;
import com.iformall.service.wechat.FmOpenService;
import com.iformall.utils.Constant;
import com.iformall.utils.IPUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/api/user")
@Api(description = "用户登陆授权相关接口")
public class WxUserGrantController extends BaseController {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private boolean isFmOpen;

    @Autowired
    private WxCUserTokenService userTokenService;

    @Autowired
    private WxCUserService wxCUserService;

    @Autowired
    private WxCUserBasicInfoService wxCUserBasicInfoService;

    @Autowired
    private WxCUserCarService wxCUserCarService;

    @Autowired
    private WxScoreRulesService wxScoreRulesService;

    @Autowired
    WxLevelConfigService wxLevelConfigService;

    @Autowired
    WxCUserTagsService wxCUserTagsService;

    @Autowired
    WxAppinfoService wxAppinfoService;

    @Autowired
    WxAuthorizerInfoService wxAuthorizerInfoService;

    @Autowired
    private FmOpenService openService;

    @Autowired
    WxMerchantService wxMerchantService;

    @Autowired
    WxCouponOrderService wxCouponOrderService;

    @Autowired
    WxCreditHistoryService wxCreditHistoryService;

    /**
     * 微信消息服务验证
     *
     * @param response
     * @param request
     * @throws IOException
     */
    @AuthIgnore
    @RequestMapping(value = "/signature")
    @ResponseBody
    public void signature(HttpServletResponse response, HttpServletRequest request) throws IOException {


        String signature = request.getParameter("signature");
        String timestamp = request.getParameter("timestamp");
        String nonce = request.getParameter("nonce");
        String echostr = request.getParameter("echostr");

        logger.warn("收到的微信服务验证信息：" + signature + "\n" + timestamp + "\n" + nonce + "\n" + echostr);
        PrintWriter out = response.getWriter();
        // 通过检验signature对请求进行校验，若校验成功则原样返回echostr，表示接入成功，否则接入失败
        // 当前无法确定此消息的appId及token, 所以直接返回echostr
        //if (CheckUtil.checkSignature(wp.getToken(), signature, timestamp, nonce)) {
        out.print(echostr);
        logger.warn("微信服务验证成功====================" + echostr);
        System.out.println("微信服务验证成功！");
        //}
        out.close();
    }

    /**
     * 用户登录
     *
     * @param map
     * @return
     */
    @AuthIgnore
    @PostMapping("/login")
    @ApiOperation(value = "用户登录", notes = "{\"appId\":\"string\",\"code\":\"string\",\"scene\":\"string\",\"sceneAddress\":\"string\",\"latitude\":\"string\",\"longitude\":\"string\",\"systemInfo\":\"string\"}")
    public ResultData userLogin(@RequestBody Map<String, String> map) {
        logger.debug(map.toString());

        Map resultMap = new HashMap();

        String appId = map.get("appId");
        String code = map.get("code");
        String sceneAddress = map.get("sceneAddress");
        String scene = map.get("scene");
        String longitude = map.get("longitude");
        String latitude = map.get("latitude");
        String systemInfo = map.get("systemInfo");
        //登录凭证不能为空
        if (StringUtils.isBlank(appId)) {
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "appId不能为空");
        }
        if (StringUtils.isBlank(code)) {
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "code不能为空");
        }

        // 通过authorizerInfo得到tenant_id
        WxAuthorizerInfo wxAuthorizerInfo = null;
        WxAppinfo wxAppinfo = null;
        WxMaService wxMaService = null;

        wxAuthorizerInfo = wxAuthorizerInfoService.getByAppId(appId);
        if (wxAuthorizerInfo == null) {
            return new ResultData(ErrorCode.APP_ID_NOT_FOUND);
        }

        if (isFmOpen) {
            wxMaService = openService.getWxOpenComponentService().getWxMaServiceByAppid(appId);
        } else {
            wxAppinfo = getAppInfo(appId);
            if (wxAppinfo == null) {
                return new ResultData(ErrorCode.APP_ID_NOT_FOUND);
            }
            wxMaService = getWeappServiceByAppInfo(wxAppinfo);

            if (StringUtils.isBlank(wxAppinfo.getAccessToken())) {
                // 如果没有accessToken,主动获取保存到数据库中，下次访问可以拿来使用
                updateAppAccessToken(wxAppinfo, wxMaService);
                wxMaService = getWeappServiceByAppInfo(wxAppinfo);

            } else {
                // 检查token是否已过期, 1小时就重新获取
                Date curDate = new Date();
                if (curDate.getTime() > wxAppinfo.getLastTokenTime().getTime() + Constant.H_EXPIRE) {
                    updateAppAccessToken(wxAppinfo, wxMaService);
                    wxMaService = getWeappServiceByAppInfo(wxAppinfo);
                }
            }
        }

        String token = null;
        String session_key = null;
        String openId = null;
        String unionId = null;
        boolean boolHaveUnionId = false;
        boolean boolFindByUnionId = false;
        Long userId = null;

        try {
            WxMaJscode2SessionResult session = wxMaService.jsCode2SessionInfo(code);
            //获取会话密钥（session_key）
            session_key = session.getSessionKey();
            openId = session.getOpenid();
            unionId = session.getUnionid();
            if (StringUtils.isNotBlank(unionId)) {
                boolHaveUnionId = true;
            }

            logger.info("session_key: " + session_key + ", openId: " + openId + ", unionId: " + unionId);
            resultMap.put("openId", openId);
        } catch (WxErrorException e) {
            logger.error(e.getMessage(), e);
            return new ResultData(ErrorCode.SESSION_KEY_DECODE_ERR, resultMap);
        }

        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String ipaddress = IPUtil.getIpAddr(request);

        WxCUser newUser = new WxCUser();
        newUser.setTenantId(wxAuthorizerInfo.getTenantId());
        newUser.setAppId(appId);
        newUser.setOpenId(openId);
        if (boolHaveUnionId) {
            newUser.setUnionId(unionId);
        }

        WxCUser oldUser = null;
        if (boolHaveUnionId) {
            // 优先根据unionId查询
            WxCUser userQ = new WxCUser();
            userQ.setTenantId(wxAuthorizerInfo.getTenantId());
            userQ.setUnionId(unionId);
            oldUser = wxCUserService.getByObject(userQ);
            if(oldUser != null) {
                boolFindByUnionId = true;
            }
        }
        if (oldUser == null) {
            oldUser = wxCUserService.getByOpenId(newUser);
        }
        if (oldUser != null) {
            // 已有用户
            token = oldUser.createToken(new Date());

            resultMap.put("token", token);
            request.setAttribute(Constant.LOGIN_USER_KEY, oldUser.getId());
            request.setAttribute(Constant.TENANT_ID, oldUser.getTenantId());

            oldUser.setRegisterIp(ipaddress);
            oldUser.setSessionKey(session_key);
            oldUser.setAppId(appId);
            oldUser.setOpenId(openId);
            if (boolHaveUnionId) {
                oldUser.setUnionId(unionId);
            }
            if (StringUtils.isNotBlank(wxAuthorizerInfo.getOpenAppid())) {
                oldUser.setOpenAppId(wxAuthorizerInfo.getOpenAppid());
            }
            if (StringUtils.isBlank(oldUser.getSceneAddress()) ||
                    oldUser.getSceneAddress().equalsIgnoreCase("undefined")) {   // from app.js onLaunch.options.scene
                oldUser.setSceneAddress(sceneAddress);
            }
            if (StringUtils.isBlank(oldUser.getScene()) ||
                    oldUser.getScene().equals("undefined")) {                                // from pages/index/index onLoad.options.scene
                oldUser.setScene(scene);
            }
            if (StringUtils.isNotBlank(longitude)) {
                oldUser.setLongitude(BigDecimal.valueOf(Double.valueOf(longitude)));
            }
            if (StringUtils.isNotBlank(latitude)) {
                oldUser.setLatitude(BigDecimal.valueOf(Double.valueOf(latitude)));
            }

            if (StringUtils.isNotBlank(systemInfo)) {
                JSONObject extraInfo = new JSONObject();
                extraInfo.put("systemInfo", JSONObject.parseObject(systemInfo));
                oldUser.setExtraInfo(extraInfo.toJSONString());
            }

            oldUser.setLoginCount(oldUser.getLoginCount() + 1);
            userTokenService.saveOrUpdate(oldUser);

            // 登录后处理
            int score = wxCUserService.actionAfterLogin(oldUser, boolFindByUnionId);
            resultMap.put("score", score);
        } else {
            // 新用户
            newUser.setTenantId(wxAuthorizerInfo.getTenantId());
            token = newUser.createToken(new Date());

            newUser.setRegisterIp(ipaddress);
            if (StringUtils.isBlank(newUser.getSceneAddress()) ||
                    newUser.getSceneAddress().equalsIgnoreCase("undefined")) { // from app.js onLaunch.options.scene
                newUser.setSceneAddress(sceneAddress);
            }
            if (StringUtils.isBlank(newUser.getScene()) ||
                    newUser.getScene().equals("undefined")) {                              // from pages/index/index onLoad.options.scene
                newUser.setScene(scene);
            }
            newUser.setSessionKey(session_key);
            if (StringUtils.isNotBlank(longitude)) {
                newUser.setLongitude(BigDecimal.valueOf(Double.valueOf(longitude)));
            }
            if (StringUtils.isNotBlank(latitude)) {
                newUser.setLatitude(BigDecimal.valueOf(Double.valueOf(latitude)));
            }

            if (StringUtils.isNotBlank(systemInfo)) {
                JSONObject extraInfo = new JSONObject();
                extraInfo.put("systemInfo", JSONObject.parseObject(systemInfo));
                newUser.setExtraInfo(extraInfo.toJSONString());
            }
            newUser.setLoginCount(0);

            userTokenService.saveOrUpdate(newUser);

            resultMap.put("token", token);
            request.setAttribute(Constant.LOGIN_USER_KEY, newUser.getId());
            request.setAttribute(Constant.TENANT_ID, newUser.getTenantId());

            // 登录后处理
            int score = wxCUserService.actionAfterLogin(newUser, null);
            resultMap.put("score", score);
        }

        return new ResultData(resultMap);
    }

    @PostMapping("/updateScene")
    @ApiOperation(value = "用户更新scene", notes = "{\"scene\":\"string\"}")
    public ResultData updateScene(@RequestBody Map<String, String> map) {
        logger.debug(map.toString());

        String scene = map.get("scene");

        WxCUser user = getUser();
        if (StringUtils.isBlank(user.getScene())) {
            if(StringUtils.isNotBlank(scene)) {
                user.setScene(scene);
                wxCUserService.updateScene(user);
            }
        }
        return new ResultData();
    }

    @PostMapping("/updateLBS")
    @ApiOperation(value = "用户更新位置信息", notes = "{\"latitude\":\"string\",\"longitude\":\"string\"}")
    public ResultData updateLBS(@RequestBody Map<String, String> map) {
        logger.debug(map.toString());

        String longitude = map.get("longitude");
        String latitude = map.get("latitude");

        WxCUser user = getUser();
        if (!StringUtils.isBlank(longitude))
            user.setLongitude(BigDecimal.valueOf(Double.valueOf(longitude)));
        if (!StringUtils.isBlank(latitude))
            user.setLatitude(BigDecimal.valueOf(Double.valueOf(latitude)));
        wxCUserService.updateLBS(user);
        return new ResultData();
    }

    @PostMapping("/updateExtInfo")
    @ApiOperation(value = "用户更新扩展信息(手机)", notes = "{\"systemInfo\":\"string\"}")
    public ResultData updateExtInfo(@RequestBody Map<String, String> map) {
        logger.debug(map.toString());

        String systemInfo = map.get("systemInfo");

        WxCUser user = getUser();
        if (StringUtils.isNotBlank(systemInfo)) {
            JSONObject extraInfo = new JSONObject();
            extraInfo.put("systemInfo", JSONObject.parseObject(systemInfo));
            user.setExtraInfo(extraInfo.toJSONString());
        }
        wxCUserService.updateExtInfo(user);
        return new ResultData();
    }

    /**
     * WxAppInfo更新accessToken
     *
     * @param wxAppinfo
     * @param wxMaService
     */
    private void updateAppAccessToken(WxAppinfo wxAppinfo, WxMaService wxMaService) {
        try {
            String accessToken = wxMaService.getAccessToken(true);
            wxAppinfo.setAccessToken(accessToken);
            wxAppinfo.setLastTokenTime(new Date());
            wxAppinfo.setExpiresIn(7200);
            wxAppinfoService.saveOrUpdate(wxAppinfo);
        } catch (WxErrorException e) {
            logger.error(e.getMessage());
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
    }

    /**
     * 获取用户的昵称等信息
     *
     * @param map
     * @return
     */
    @PostMapping("/getUserInfo")
    @ApiOperation(value = "授权后获取用户的昵称,unionId等信息", notes = "{\"encryptedData\":\"string\",\"iv\":\"string\"}")
    public ResultData getUserInfo(@RequestBody Map<String, String> map) {
        logger.debug(map.toString());
        Map resultMap = new HashMap();

        String encryptedData = map.get("encryptedData");
        String iv = map.get("iv");

        if (StringUtils.isBlank(encryptedData)) {
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "encryptedData不能为空");
        }
        if (StringUtils.isBlank(iv)) {
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "iv不能为空");
        }

        WxCUser user = getUser();

        if (user != null) {
            logger.debug(user.toString());

            boolean bFirstNickName = false;
            if(StringUtils.isBlank(user.getNickName())) {
                bFirstNickName = true;
            }

            WxMaService wxMaService = getWeappService(user.getAppId());

            String session_key = user.getSessionKey();
            try {
                // 解密用户信息
                WxMaUserInfo userInfo = wxMaService.getUserService().getUserInfo(session_key, encryptedData, iv);
                if (userInfo != null) {
                    logger.debug(userInfo.toString());
                    user.setUnionId(userInfo.getUnionId());
                    user.setNickName(userInfo.getNickName());
                    user.setGender(Integer.parseInt(userInfo.getGender()));
                    user.setAvatarUrl(userInfo.getAvatarUrl());
                    user.setProvince(userInfo.getProvince());
                    user.setCity(userInfo.getCity());
                    user.setLanguage(userInfo.getLanguage());
                    wxCUserService.saveOrUpdate(user);

                    if(bFirstNickName) {
                        // 首次获取昵称
                        // 成长值
                        wxScoreRulesService.addScore(EnumScoreType.WECHAT_PERSION, user);
                        //增加积分
                        wxCUserService.addCredit(user, EnumScoreType.WECHAT_PERSION);
                    }

                    resultMap.put("openId", user.getOpenId());
                    resultMap.put("unionId", user.getUnionId());
                    resultMap.put("msg", "获取用户信息成功！");
                    return new ResultData(resultMap);
                } else {
                    return new ResultData(ErrorCode.NICK_NAME_DECODE_ERR, resultMap);
                }
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
                return new ResultData(ErrorCode.DB_FAIL.getCode(), "解密并保存出错", resultMap);
            }
        } else {
            return new ResultData(ErrorCode.USER_LOGIN_FAILED);
        }
    }

    /**
     * 授权后获取用户的手机号等信息
     *
     * @param map
     * @return
     */
    @PostMapping("/getUserPhone")
    @ApiOperation(value = "授权后获取用户的手机号", notes = "{\"encryptedData\":\"string\",\"iv\":\"string\"}")
    public ResultData getUserPhone(@RequestBody Map<String, String> map) {
        logger.debug(map.toString());
        Map resultMap = new HashMap();
        String encryptedData = map.get("encryptedData");
        String iv = map.get("iv");

        //登录凭证不能为空
        if (StringUtils.isBlank(encryptedData)) {
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "encryptedData 不能为空");
        }
        if (StringUtils.isBlank(iv)) {
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "iv 不能为空");
        }

        WxCUser user = getUser();

        if (user == null) {
            return new ResultData(ErrorCode.USER_IS_EMPTY);
        }

        boolean isFirstPhone = false;
        if(StringUtils.isBlank(user.getPhone())) {
            isFirstPhone = true;
        }

        WxMaService wxMaService = getWeappService(user.getAppId());

        String session_key = user.getSessionKey();
        try {
            // 解密
            WxMaPhoneNumberInfo phoneNoInfo = wxMaService.getUserService().getPhoneNoInfo(session_key, encryptedData, iv);
            if (null != phoneNoInfo) {
                logger.debug(phoneNoInfo.toString());
                user.setPhone(phoneNoInfo.getPhoneNumber());
                user.setPurePhone(phoneNoInfo.getPurePhoneNumber());
                user.setCountryCode(phoneNoInfo.getCountryCode());
                if (isFirstPhone) {
                    //检查是否存在会员信息 如果有 赋值积分
                    WxCUserBasicInfo basicInfo = wxCUserBasicInfoService.findInfoByPhone(user.getTenantId(), user.getPhone());
                    if (basicInfo != null ) {
                         int credit = user.getCredit() == null ? 0 : user.getCredit();
                         int score = user.getScore() == null ? 0 : user.getScore();
                         int memScore = basicInfo.getPoins() == null ? 0 : basicInfo.getPoins();
                         int memCredit = basicInfo.getCredit() == null ? 0 : basicInfo.getCredit();
                         user.setCredit(memCredit + credit);
                         user.setScore(memScore + score);
                    }
                }
                wxCUserService.saveOrUpdate(user);

                if(isFirstPhone) {
                    // 首次授权， 增加成长值及积分
                    // 成长值
                    user.setScore(user.getScore() + wxScoreRulesService.addScore(EnumScoreType.WECHAT_PHONE, user));
                    //增加积分
                    wxCUserService.addCredit(user, EnumScoreType.WECHAT_PHONE);
                }

                resultMap.put("msg", "授权手机成功！");
                resultMap.put("phone", phoneNoInfo.getPhoneNumber());
            } else {
                return new ResultData(ErrorCode.PHONE_DECODE_ERR, resultMap);
            }
        } catch (Exception e) {
            this.logger.error(e.getMessage(), e);
            return new ResultData(ErrorCode.DB_FAIL.getCode(), "解密并保存出错", resultMap);
        }

        if (!user.getPhone().contains("*")) { // 用户手机非加密
            // 更新到basicinfo
            saveToBasicInfo(user);
            wxCUserTagsService.triggerAssignTags(EnumAssignTagsTrigger.ASSIGN_TAGS_TRIGGER_PHONE, user);
        }

        return new ResultData(resultMap);
    }

    /**
     * 检查微信用户状态
     *
     * @return
     */
    @RequestMapping("/checkWechatStatus")
    @ApiOperation(value = "判断用户是否完成授权", notes = "")
    public ResultData checkWechatStatus() {
        Map resultMap = new HashMap();
        WxCUser user = getUser();
        if (StringUtils.isNotBlank(user.getNickName())) {
            resultMap.put("nickName", user.getNickName());
        } else {
            logger.warn("用户昵称未授权，跳转到用户授权页！");
            return new ResultData(ErrorCode.NICK_NAME_NOT_FOUND.getCode(), "用户昵称未授权，请跳转到用户昵称授权页！", resultMap);
        }
        if (StringUtils.isNotBlank(user.getPhone())) {
            resultMap.put("phone", user.getPhone());
        } else {
            if (StringUtils.isBlank(user.getPhone())) {
                logger.warn("用户手机号未授权，跳转到授权手机号页！");
                return new ResultData(ErrorCode.PHONE_NOT_FOUND.getCode(), "用户手机号未授权，请跳转到授权手机号页！", resultMap);
            }
            if (user.getPhone().contains("*")) {
                logger.warn("用户手机号已加密，跳转到手工输入手机号页！");
                return new ResultData(ErrorCode.PHONE_IS_ENCRYPTED.getCode(), "用户手机号已加密，手工输入手机号页！", resultMap);
            }
        }
        return new ResultData(Result.SUCCESS, "是老用户，已完成用户昵称/手机号授权", resultMap);
    }

    /**
     * 检查用户状态
     *
     * @return
     */
    @RequestMapping("/checkUserStatus")
    @ApiOperation(value = "判断用户是否完成昵称授权", notes = "")
    public ResultData checkUserStatus() {
        Map resultMap = new HashMap();
        WxCUser user = getUser();
        if (StringUtils.isNotBlank(user.getNickName())) {
            resultMap.put("nickName", user.getNickName());
        } else {
            logger.warn("用户昵称未授权，跳转到用户授权页！");
            return new ResultData(ErrorCode.NICK_NAME_NOT_FOUND.getCode(), "用户昵称未授权，请跳转到用户昵称授权页！", resultMap);
        }
        return new ResultData(Result.SUCCESS, "是老用户，已完成用户昵称授权", resultMap);
    }

    /**
     * 检查用户状态
     *
     * @return
     */
    @RequestMapping("/checkPhoneStatus")
    @ApiOperation(value = "判断用户是否完成手机授权", notes = "")
    public ResultData checkPhoneStatus() {
        Map resultMap = new HashMap();
        WxCUser user = getUser();
        if (StringUtils.isNotBlank(user.getPhone())) {
            resultMap.put("phone", user.getPhone());
        } else {
            if (StringUtils.isBlank(user.getPhone())) {
                logger.warn("用户手机号未授权，跳转到授权手机号页！");
                return new ResultData(ErrorCode.PHONE_NOT_FOUND.getCode(), "用户手机号未授权，请跳转到授权手机号页！", resultMap);
            }
            if (user.getPhone().contains("*")) {
                logger.warn("用户手机号已加密，跳转到手工输入手机号页！");
                return new ResultData(ErrorCode.PHONE_IS_ENCRYPTED.getCode(), "用户手机号已加密，手工输入手机号页！", resultMap);
            }
        }
        return new ResultData(Result.SUCCESS, "是老用户，已完成手机号授权", resultMap);
    }

    @ApiOperation("获取当前用户信息")
    @GetMapping("/userinfo")
    public ResultData getUserInfo() {
        WxCUser user = getUser();
        WxCUserVo userVo = new WxCUserVo();
        org.springframework.beans.BeanUtils.copyProperties(user, userVo);
        if (userVo.getScore() == null)
            userVo.setScore(0);
        Integer levelScore = 0;
        Integer levelTarget= 0;
        userVo.setLevelName(WxLevelConfigService.DEFAULT_LEVEL);
        List<WxLevelConfig> levelList = wxLevelConfigService.getByTenantId(user.getTenantId());
        if (levelList.size() > 0)
            levelTarget = levelList.get(0).getPoints();
        for (int i = 0; i<levelList.size(); i++) {
            WxLevelConfig levelConfig = levelList.get(i);
            if (userVo.getScore() >= levelConfig.getPoints()) {
                userVo.setLevelId(levelConfig.getId());
                userVo.setLevelName(levelConfig.getLevel());
                levelScore = levelConfig.getPoints();
                if (i+1 < levelList.size())
                    levelTarget =  levelList.get(i+1).getPoints();
            }
        }

        if (levelTarget == 0) {
            userVo.setUpgradePercent(0);
            userVo.setUpgradeScore(0);
        } else if(levelScore == levelTarget) {
            userVo.setUpgradePercent(100);
            userVo.setUpgradeScore(0);
        } else {
            userVo.setUpgradePercent((userVo.getScore()-levelScore)*100/(levelTarget-levelScore));
            userVo.setUpgradeScore(levelTarget-userVo.getScore());
        }

        WxCUserBasicInfo wxCUserBasicInfo = wxCUserBasicInfoService.getById(user.getId());
        if (wxCUserBasicInfo != null) {
            userVo.setName(wxCUserBasicInfo.getName());
            userVo.setBirthdate(wxCUserBasicInfo.getBirthdate());
            userVo.setSex(wxCUserBasicInfo.getSex());
            userVo.setAddress(wxCUserBasicInfo.getAddress());
            userVo.setStatus(wxCUserBasicInfo.getStatus());
        }

        return new ResultData(userVo);
    }

    @ApiOperation("当前用户名下是否有车")
    @GetMapping("/carCount")
    public ResultData carCount() {
        WxCUser user = getUser();
        WxCUserCar userCar = new WxCUserCar();
        userCar.setTenantId(user.getTenantId());
        userCar.setCUserId(user.getId());
        Integer count = wxCUserCarService.countUserCar(userCar);
        if (count > 0) {
            Map returnMap = new HashMap();
            String phone = user.getPhone();
            if (phone.contains("*"))
                phone = user.getVerifyCodePhone();
            returnMap.put("phone", phone);
            returnMap.put("count", count);
            return new ResultData(Result.SUCCESS, "count获取成功", returnMap);
        } else {
            Map returnMap = new HashMap();
            returnMap.put("count", count);
            return new ResultData(Result.SUCCESS, "count获取成功", returnMap);
        }
    }

    @ApiOperation("获取当前用户车牌列表")
    @GetMapping("/carList")
    public ResultData getCarList() {
        WxCUserCar userCar = new WxCUserCar();
        userCar.setTenantId(getTenantId());
        userCar.setCUserId(getUserId());
        List<WxCUserCar> list = wxCUserCarService.getList(userCar);
        return new ResultData(Result.SUCCESS, "获取查询成功", list);
    }

    /**
     * 授权后获取用户的手机号等信息
     *
     * @param map
     * @return
     */
    @PostMapping("/getWeRunData")
    @ApiOperation(value = "获取用户过去三十天微信运动步数", notes = "{\"encryptedData\":\"string\",\"iv\":\"string\"}")
    public ResultData getWeRunData(@RequestBody Map<String, String> map) {
        logger.debug(map.toString());
        String encryptedData = map.get("encryptedData");
        String iv = map.get("iv");

        //登录凭证不能为空
        if (StringUtils.isBlank(encryptedData)) {
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "encryptedData 不能为空");
        }
        if (StringUtils.isBlank(iv)) {
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "iv 不能为空");
        }

        WxCUser user = getUser();

        String session_key = user.getSessionKey();
        try {
            // 解密
            String weRunDataStr = WxMaCryptUtils.decrypt(session_key, encryptedData, iv);
            if (null != weRunDataStr) {
                Object obj = JSON.parse(weRunDataStr);
                return new ResultData(obj);
            } else {
                return new ResultData(ErrorCode.WE_RUN_DATA_DECODE_ERR);
            }
        } catch (Exception e) {
            this.logger.error(e.getMessage(), e);
            return new ResultData(ErrorCode.WE_RUN_DATA_DECODE_ERR);
        }
    }

    /**
     * 用户更新信息
     *
     * @return
     */
    @PostMapping("/updateUserInfo")
    @ApiOperation(value = "用户更新信息", notes = "")
    public ResultData updateUserInfo(@RequestBody WxCUserBasicInfo wxCUserBasicInfo) {
        if (wxCUserBasicInfo == null)
            return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL);
        if (wxCUserBasicInfoService.getById(getUserId()) == null)
            return new ResultData(ErrorCode.USER_IS_NOT_MEMBER);

        if (wxCUserBasicInfo.getName() != null ||
                wxCUserBasicInfo.getBirthdate() != null ||
                wxCUserBasicInfo.getSex() != null ||
                wxCUserBasicInfo.getAddress() != null) {
            WxCUserBasicInfo record = new WxCUserBasicInfo();
            record.setName(wxCUserBasicInfo.getName());
            record.setBirthdate(wxCUserBasicInfo.getBirthdate());
            record.setSex(wxCUserBasicInfo.getSex());
            record.setAddress(wxCUserBasicInfo.getAddress());
            record.setId(getUserId());
            record.setUpdateDate(new Date());
            wxCUserBasicInfoService.update(record);
            wxScoreRulesService.addScore(EnumScoreType.COMPLETE_INFO, record);
            //增加积分
            WxCreditHistory wxCreditHistory = new WxCreditHistory();
            wxCreditHistory.setCUserId(record.getId());
            wxCreditHistory.setTenantId(getTenantId());
            wxCreditHistory.setCreateDate(new Date());
            wxCreditHistory.setCreditType(EnumScoreType.COMPLETE_INFO.getCode());
            wxCreditHistory.setOperatorType(EnumUserType.CUSER.getCode());
            wxCreditHistory.setOperatorId(getUserId());
            wxCreditHistoryService.saveOrUpdate(wxCreditHistory);
            wxCUserTagsService.triggerAssignTags(EnumAssignTagsTrigger.ASSIGN_TAGS_TRIGGER_IMPORT, record);
        }
        return new ResultData();
    }

    /**
     * 获取用户折扣率
     *
     * @return
     */
    @RequestMapping("/getDiscountInfo")
    @ApiOperation(value = "获取用户折扣率", notes = "")
    public ResultData getDiscountInfo() {

        WxCUser user = getUser();

        List<WxLevelConfig> levelList = wxLevelConfigService.getByTenantId(user.getTenantId());

        String level = WxLevelConfigService.DEFAULT_LEVEL;
        Long levelId = 0L;
        for (WxLevelConfig levelConfig : levelList) {
            if (user.getScore() >= levelConfig.getPoints()) {
                if (levelConfig.getDiscountEnable().equals(EnumLevelConfigDiscountStatus.ENABLE.getCode()))
                    levelId = levelConfig.getId();
                level = levelConfig.getLevel();
            }
        }
        WxLevelMerchant levelMerchant = new WxLevelMerchant();
        levelMerchant.setLevelId(levelId);
        List<WxLevelMerchantCVo> levelMerchantList = wxLevelConfigService.findListCVo(levelMerchant);

        Map<String, Object> result = new HashMap();
        result.put("id", user.getId());
        result.put("level", level);
        result.put("levelMerchantList", levelMerchantList);
        return new ResultData(result);
    }

}
