package com.kmall.api.api;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.kmall.api.annotation.IgnoreAuth;
import com.kmall.api.cache.UserTokenCache;
import com.kmall.api.entity.*;
import com.kmall.api.service.*;
import com.kmall.api.util.ApiBaseAction;
import com.kmall.api.util.ApiUserUtils;
import com.kmall.api.util.CommonUtil;
import com.kmall.common.utils.ApiRRException;
import com.kmall.common.utils.CharUtil;
import com.qiniu.util.StringUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * API登录授权
 *
 * @author Scott
 * @email
 * @date 2017-03-23 15:31
 */
@RestController
@RequestMapping("/api/auth")
public class ApiAuthController extends ApiBaseAction {
    private Log logger = LogFactory.getLog(ApiAuthController.class);
    @Autowired
    private ApiUserService userService;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private ApiStoreService apiStoreService;
    @Autowired
    private ApiMerchUserService apiMerchUserService;
    @Autowired
    private ApiThirdMerchantBizService apiThirdMerchantBizService;
    public static final String IS_REFUSED_LOGIN = "isRefusedLogin";

    /**
     * 授权登录保存用户信息，以及redis的token信息
     */
    @IgnoreAuth
    @PostMapping("login_by_weixin")
    public Object loginByWeixin(HttpServletRequest request) {
        //从header中获取IS_REFUSED_LOGIN
        String isRefusedLogin = request.getHeader(IS_REFUSED_LOGIN);
        Map<String, Object> resultObj = Maps.newHashMap();
        JSONObject jsonParam = this.getJsonRequest();
        FullUserInfo fullUserInfo = null;
        Long storeId = jsonParam.getLong("storeId");
        String merchSn = (String)jsonParam.get("merchSn");
        String code = "";
        if (!StringUtils.isNullOrEmpty(jsonParam.getString("code"))) {
            code = jsonParam.getString("code");
        }
        if (null != jsonParam.get("userInfo")) {
            fullUserInfo = jsonParam.getObject("userInfo", FullUserInfo.class);
        }
        UserInfo userInfo = fullUserInfo.getUserInfo();
        if(userInfo == null){
            return toResponsFail("登录失败");
        }
        //获取openid
        String requestUrl = ApiUserUtils.getWebAccess(code);//通过自定义工具类组合出小程序需要的登录凭证 code
        logger.info("》》》组合token为：" + requestUrl);
        JSONObject sessionData = CommonUtil.httpsRequest(requestUrl, "GET", null);
        logger.info("》》》sessionData为：" + sessionData);

        if (null == sessionData) {
            return toResponsFail("登录失败");
        }
        String openId = sessionData.getString("openid");
        if (StringUtils.isNullOrEmpty(openId)) {
            return toResponsFail("登录失败");
        }
        //验证用户信息完整性
        String sha1 = CommonUtil.getSha1(fullUserInfo.getRawData() + sessionData.getString("session_key"));
        if (!fullUserInfo.getSignature().equals(sha1)) {
            return toResponsFail("登录失败");
        }
        Date nowTime = new Date();
        UserVo userVo = userService.queryByOpenId(openId);
        userInfo.setNickName(filterEmoji(userInfo.getNickName()));;
        if (null == userVo) {
            userVo = new UserVo();
            userVo.setPassword(openId);
            userVo.setRegister_time(nowTime);
            userVo.setRegister_ip(this.getClientIp());
            userVo.setLast_login_ip(userVo.getRegister_ip());
            userVo.setLast_login_time(userVo.getRegister_time());
            userVo.setWeixin_openid(sessionData.getString("openid"));
            userVo.setAvatar(userInfo.getAvatarUrl());
            userVo.setGender(userInfo.getGender()); // //性别 0：未知、1：男、2：女
            userVo.setNickname(userInfo.getNickName());
            userVo.setUser_level_id(1);
            userService.save(userVo);

        } else {
            userVo.setLast_login_ip(this.getClientIp());
            userVo.setLast_login_time(nowTime);
            userVo.setAvatar(userInfo.getAvatarUrl());
            userVo.setGender(userInfo.getGender()); // //性别 0：未知、1：男、2：女
            userService.update(userVo);
        }
        if(userVo.getId()!=null){
            isRefusedLogin = "false";
        }
        Map<String, Object> tokenMap = tokenService.createAndUpdateToken(userVo.getWeixin_openid(), storeId,userVo.getId(),merchSn, isRefusedLogin);
        String token = MapUtils.getString(tokenMap, "token");

        if (null == userInfo || StringUtils.isNullOrEmpty(token)) {
            return toResponsFail("登录失败");
        }

        resultObj.put("token", token);
        resultObj.put("userInfo", userInfo);
        resultObj.put("userId", userVo.getId());
        return toResponsSuccess(resultObj);
    }

    /**
     * 保存token到redis，授权登录或未登录保存token
     * @param request
     * @return
     */
    @IgnoreAuth
    @PostMapping("loginSaveToken")
    public Object loginSaveToken(HttpServletRequest request) {
        //从header中获取IS_REFUSED_LOGIN
        String isRefusedLogin = request.getHeader(IS_REFUSED_LOGIN);
        Map<String, Object> resultObj = Maps.newHashMap();
        JSONObject jsonParam = this.getJsonRequest();
        Long storeId = jsonParam.getLong("storeId");
        String merchSn = (String)jsonParam.get("merchSn");
        UserInfo userInfo = null;
        if (null != jsonParam.get("userInfo")) {
            userInfo = jsonParam.getObject("userInfo", UserInfo.class);
        }
//        if(userInfo == null){
//            return toResponsFail("登录失败");
//        }
        String code = "";
        UserVo userVo = null;
        String openId = "";
        if (!StringUtils.isNullOrEmpty(jsonParam.getString("code"))) {
            code = jsonParam.getString("code");
            //获取openid
            String requestUrl = ApiUserUtils.getWebAccess(code);//通过自定义工具类组合出小程序需要的登录凭证 code
            logger.info("》》》组合token为：" + requestUrl);
            JSONObject sessionData = CommonUtil.httpsRequest(requestUrl, "GET", null);
            logger.info("》》》sessionData为：" + sessionData);

            if (null == sessionData) {
                return toResponsFail("登录失败");
            }
            openId = sessionData.getString("openid");
            if (StringUtils.isNullOrEmpty(openId)) {
                return toResponsFail("登录失败");
            }
            userVo = userService.queryByOpenId(openId);
            if (null == userVo) {
                userVo = new UserVo();
                if(!StringUtils.isNullOrEmpty(openId)){
                    userVo.setPassword(openId);
                    userVo.setWeixin_openid(openId);
                }
                userVo.setRegister_time(new Date());
                userVo.setRegister_ip(this.getClientIp());
                userVo.setLast_login_ip(userVo.getRegister_ip());
                userVo.setLast_login_time(userVo.getRegister_time());
                if(userInfo != null){
                    userVo.setAvatar(userInfo.getAvatarUrl());
                    userVo.setGender(userInfo.getGender()); // //性别 0：未知、1：男、2：女
                    userVo.setNickname(filterEmoji(userInfo.getNickName()));
                }
                userVo.setUser_level_id(1);
                userService.save(userVo);
            }
        }
        Long userId = null;
        if(userVo != null) {
            userVo.setLast_login_ip(this.getClientIp());
            userVo.setLast_login_time(new Date());
            if(userInfo != null){
                userVo.setAvatar(userInfo.getAvatarUrl());
                userVo.setGender(userInfo.getGender()); // //性别 0：未知、1：男、2：女
                userVo.setNickname(filterEmoji(userInfo.getNickName()));
            }
            userService.update(userVo);
            userId = userVo.getId();
            if(userId != null){
                isRefusedLogin = "false";
            }
        }
        Map<String, Object> tokenMap = tokenService.createAndUpdateToken(openId, storeId, userId ,merchSn, isRefusedLogin);
        String token = MapUtils.getString(tokenMap, "token");

        if (StringUtils.isNullOrEmpty(token)) {
            return toResponsFail("登录失败");
        }

        resultObj.put("token", token);
        resultObj.put("userInfo", userInfo);
        resultObj.put("userId", userId);
        return toResponsSuccess(resultObj);
    }

    /**
     * 校验当前token是否有效
     * @param request
     * @return
     */
    @IgnoreAuth
    @PostMapping("checkToken")
    public Object checkToken(HttpServletRequest request) {
        Map<String, Object> resultObj = Maps.newHashMap();
        JSONObject jsonParam = this.getJsonRequest();
        String token = (String)jsonParam.get("token");
        String isRefusedLogin = (String)jsonParam.get("isRefusedLogin");
        String userId = (String)jsonParam.get("userId");
        Integer storeId = (Integer)jsonParam.get("storeId");
        //查询token信息
        TokenEntity tokenEntity = null;
        if(!StringUtils.isNullOrEmpty(userId) && (isRefusedLogin==null||!isRefusedLogin.equalsIgnoreCase("true"))) {
            tokenEntity = UserTokenCache.getUserInfoByToken(token);
        }
        if(token != null && !StringUtils.isNullOrEmpty(userId) && (isRefusedLogin==null ||
                !isRefusedLogin.equalsIgnoreCase("true"))) {
            tokenEntity = UserTokenCache.getUserInfoByToken(token);
        }
        if(isRefusedLogin!=null){
            if(storeId != null && isRefusedLogin.equalsIgnoreCase("true")){
                tokenEntity = UserTokenCache.getStoreByTokenByRefused(token);
            }
        }
        if ((tokenEntity == null || tokenEntity.getExpireTime().getTime() < System.currentTimeMillis())) {
            logger.info("已授权，且token不为空，根据token查询token信息为空，校验token失效");//生成一个token
            throw new ApiRRException("token失效", 401);
        }

        resultObj.put("token", tokenEntity.getToken());
        return toResponsSuccess(resultObj);
    }
    /**
     * 将emoji表情替换成空串
     * @param source
     * @return 过滤后的字符串
     **/
    public static String filterEmoji(String source) {
        if (source != null && source.length() > 0) {
            return source.replaceAll("[\ud800\udc00-\udbff\udfff\ud800-\udfff]", "");
        } else {
            return source;
        }
    }

    /**
     * 根据经纬度选择门店,审核成功删除
     */
    @GetMapping("nearbyLists")
    @IgnoreAuth
    public Object nearbyLists(@RequestParam BigDecimal latitude, @RequestParam BigDecimal longitude, @RequestParam String storeId,
                              @RequestParam String thirdPartyMerchCode, HttpServletRequest request) {
        //从header中获取IS_REFUSED_LOGIN
        String isRefusedLogin = request.getHeader(IS_REFUSED_LOGIN);
        Map param = Maps.newHashMap();
        if(org.apache.commons.lang3.StringUtils.isNotEmpty(storeId)){
            param.put("storeId", storeId);
        }
        if(org.apache.commons.lang3.StringUtils.isNotEmpty(thirdPartyMerchCode)){
            param.put("thirdPartyMerchCode", thirdPartyMerchCode);
        }
        param.put("latitude", latitude);
        param.put("longitude", longitude);
        List<StoreVo> storeVoList = apiStoreService.queryNearbyList(param);

        if(org.apache.commons.lang3.StringUtils.isNotEmpty(storeId)){
            if(storeVoList.size()==0){
                Map param2 = Maps.newHashMap();
                if(org.apache.commons.lang3.StringUtils.isNotEmpty(thirdPartyMerchCode)){
                    param2.put("thirdPartyMerchCode", thirdPartyMerchCode);
                }
                param2.put("latitude", latitude);
                param2.put("longitude", longitude);
                storeVoList = apiStoreService.queryNearbyList(param2);
            }
        }
        if (null != storeVoList && storeVoList.size() > 0 && null != getOpenId()) {
            tokenService.createAndUpdateToken(getOpenId(), storeVoList.get(0).getId(),getUserId(),storeVoList.get(0).getMerchSn(),isRefusedLogin);
        }
        return toResponsSuccess(storeVoList);
    }

    @GetMapping("updateStoreLoadGoodsById")
    @IgnoreAuth
    public Object updateStoreLoadGoodsById(@RequestParam String storeId) {
        MerchUserVo merchUserVo = new MerchUserVo();
        merchUserVo.setStoreId(Integer.valueOf(storeId));
        merchUserVo.setUserId(Integer.parseInt(String.valueOf(getUserId())));
        merchUserVo.setIsLoadGoods("0");//门店商品是否修改字段更新为否
        apiMerchUserService.updateStoreLoadGoodsById(merchUserVo);
        return toResponsSuccess("成功");
    }

    /**
     * 根据城市获取门店
     */
    @GetMapping("storeListByCity")
    @IgnoreAuth
    public Object storeListByCity(@RequestParam String provinceName, @RequestParam String cityName, @RequestParam String countyName) {
        Map param = Maps.newHashMap();
        param.put("province_name", provinceName);
        param.put("city_name", cityName);
        param.put("county_name", countyName);

        List<StoreVo> storeVoList = apiStoreService.queryList(param);
        return toResponsSuccess(storeVoList);
    }

    /**
     * 选择门店Id
     */
    @PostMapping("chooseStoreId")
    public Object chooseStoreId() {
        JSONObject jsonParam = this.getJsonRequest();
        String openId = getOpenId();
        Long storeId = jsonParam.getLong("storeId");
        String merchSn = (String)jsonParam.get("merchSn");
        String isRefusedLogin = (String)jsonParam.get("isRefusedLogin");
        logger.info("选择门店参数：storeId："+storeId +"；merchSn："+merchSn+"；isRefusedLogin："+isRefusedLogin);
        //
        Map<String, Object> resultObj = Maps.newHashMap();
        Map<String, Object> tokenMap = tokenService.createAndUpdateToken(openId, storeId, getUserId(), merchSn, isRefusedLogin);
        String token = MapUtils.getString(tokenMap, "token");
        resultObj.put("token", token);
        return toResponsSuccess(resultObj);
    }

    @IgnoreAuth
    @PostMapping("updateLoginUser")
    public Object updateLoginUser() {
        JSONObject jsonParam = this.getJsonRequest();
        Long storeId = jsonParam.getLong("storeId");
        Long userId = jsonParam.getLong("userId");
        String merchSn = (String)jsonParam.get("merchSn");
//        Date nowTime = new Date();
        UserVo userVo = userService.queryObject(userId);
        String isLoadGoods = "";
        if (null != userVo) {
            MerchUserVo merchUser = apiMerchUserService.queryObjectByStoreId(storeId,userId);
            MerchUserVo merchUserVo = new MerchUserVo();
            merchUserVo.setStoreId(Integer.parseInt(String.valueOf(storeId)));
            merchUserVo.setMerchSn(merchSn);
            merchUserVo.setUserId(Integer.parseInt(String.valueOf(userId)));
            if(merchUser != null) {
                isLoadGoods = merchUser.getIsLoadGoods();
                merchUserVo.setModTime(new Date());
                merchUserVo.setId(merchUser.getId());
                apiMerchUserService.update(merchUserVo);
            }else{
                merchUserVo.setCreateTime(new Date());
                merchUserVo.setModTime(new Date());
                merchUserVo.setIsLoadGoods("0");
                apiMerchUserService.save(merchUserVo);
            }
        }
        ThirdMerchantBizVo thirdMerchantBizVo = apiThirdMerchantBizService.queryDataByStoreId(storeId);
        if(thirdMerchantBizVo != null){
            thirdMerchantBizVo.setIsLoadGoods(isLoadGoods);
        }
        return toResponsSuccess(thirdMerchantBizVo);
    }

    @GetMapping("getOpenId")
    @IgnoreAuth
    public Object getOpenId(@RequestParam String code) {
        //获取openid
        String requestUrl = ApiUserUtils.getWebAccess(code);//通过自定义工具类组合出小程序需要的登录凭证 code
        logger.info("》》》组合token为：" + requestUrl);
        JSONObject sessionData = CommonUtil.httpsRequest(requestUrl, "GET", null);
        logger.info("》》》sessionData为：" + sessionData);

        if (null == sessionData) {
            return toResponsFail("登录失败");
        }
        String openId = sessionData.getString("openid");
        if (StringUtils.isNullOrEmpty(openId)) {
            return toResponsFail("登录失败");
        }
        return toResponsSuccess(openId);
    }
}
