package com.community.huiju.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.community.commom.mode.ResponseBean;
import com.community.commom.session.UserElement;
import com.community.commom.utils.BeanTools;
import com.community.huiju.common.code.ICode;
import com.community.huiju.common.code.cache.AppkeyCache;
import com.community.huiju.common.perproties.LoginCodePerproties;
import com.community.huiju.common.perproties.WeiXinPerproties;
import com.community.huiju.dao.TaUserMapper;
import com.community.huiju.enums.UserVerifyEnum;
import com.community.huiju.exception.WisdomException;
import com.community.huiju.model.TaUser;
import com.community.huiju.service.ITaUserService;
import com.community.huiju.service.WxLoginServiceI;
import com.community.huiju.vo.TaUserVO;
import com.github.sd4324530.fastweixin.api.OauthAPI;
import com.github.sd4324530.fastweixin.api.UserAPI;
import com.github.sd4324530.fastweixin.api.config.ApiConfig;
import com.github.sd4324530.fastweixin.api.response.GetUserInfoResponse;
import com.github.sd4324530.fastweixin.api.response.OauthGetTokenResponse;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Date;
import java.util.Map;

/**
 * @author FXF
 * @date 2019-03-29
 */
@Service("wxLoginService")
public class WxLoginServiceImpl implements WxLoginServiceI {
	
	private Logger logger = LoggerFactory.getLogger(WxLoginServiceImpl.class);
	
	@Autowired
	private TaUserMapper taUserMapper;

	@Autowired
	private ITaUserService iTaUserService;

	@Autowired
	@Qualifier("phoneCodeImpl")
	private ICode iCode;

	@Autowired
	private LoginCodePerproties loginCodePerproties;

	@Autowired
	private WeiXinPerproties weiXinPerproties;
	
	@Override
	public ResponseBean getOpenidByWxcode(String wxcode, HttpSession session) {
		ResponseBean responseBean = new ResponseBean();

		OauthGetTokenResponse codeResponse = getOauthGetTokenResponse(wxcode);
		String openId = codeResponse.getOpenid();
		logger.info("获取到wxcode:" + wxcode + " 获取到的openid: " + openId + "accesstoken: " + codeResponse.getAccessToken());

		//根据openId查询关联的手机号
		TaUser taUser = taUserMapper.getByOpenId(openId);
		if (null == taUser) {
			String userInfo = getWXuserInfo(codeResponse.getAccessToken(), openId);
			Map<String, Object> result = Maps.newHashMap();
			result.put("userInfo", userInfo);
			result.put("openid", openId);

			JSONObject userInfoJSON = JSONObject.parseObject(userInfo);
			String wxPar = "&openid=" + URLEncoder.encode(openId) + "&nickname=" + URLEncoder.encode(userInfoJSON.getString("nickname")) + "&headimgurl=" + URLEncoder.encode(userInfoJSON.getString("headimgurl"));
			responseBean.addError(UserVerifyEnum.NO_ACCOUNT.getMsg(), result, loginCodePerproties.getLoginCode().get(UserVerifyEnum.NO_ACCOUNT.getCode()) + wxPar);
			return responseBean;
		}

		responseBean = iTaUserService.checkLogin(responseBean, taUser, session);

		return responseBean;
	}

	/**
	 * 微信
	 * 公共方法 OauthGetTokenResponse
	 *
	 * 	可以获取 openid， AccessToken 等
	 *
	 * @param wxcode
	 * @return
	 */
	private OauthGetTokenResponse getOauthGetTokenResponse(String wxcode) {
		ApiConfig apiConfig = new ApiConfig(weiXinPerproties.getAppid(),weiXinPerproties.getSecret(), true);
		logger.info("获取微信相关信息");
		OauthAPI oauthAPI = new OauthAPI(apiConfig);
		OauthGetTokenResponse codeResponse = oauthAPI.getToken(wxcode);
		return codeResponse;
	}

	/**
	 * 微信
	 * 公共方法，获取 微信用户信息
	 * @param accessToken
	 * @param openId
	 * @return
	 */
	private String getWXuserInfo(String accessToken, String openId) {
		//根据OPENID获取用户信息
		RestTemplate restTemplate = new RestTemplate();
		String wxUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=" + accessToken + "&openid=" + openId;
		String userInfo = restTemplate.getForEntity(wxUrl,String.class).getBody();
		logger.info("获取到用户信息:" + userInfo);

		return userInfo;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public ResponseBean associatedWX(String parameter) {
		ResponseBean responseBean = new ResponseBean();

		JSONObject jsonObject = JSONObject.parseObject(parameter);
		String loginName = jsonObject.getString("loginName");
		String code = jsonObject.getString("code");

		// 检验手机号和验证码
		iCode.checkPhoneAndCode(loginName, code);

		// 获取用户
		TaUser user = iTaUserService.hasUserPhone(loginName);
		// 未注册
		if (null == user) {
			responseBean.addError(UserVerifyEnum.NO_UNREGISTERED.getCode(), UserVerifyEnum.NO_UNREGISTERED.getMsg() + "&phone=" + loginName + "&code=" + code);
			return responseBean;
		}

		// 检验微信绑定
		responseBean = checkWX(responseBean, user, parameter);

		// 检验登录房产
		responseBean = iTaUserService.checkLogin(responseBean, user, null);


		// 设置验证码为null字符
		AppkeyCache.setCache(loginName,"null");
		return responseBean;
	}

	/**
	 *  检验微信绑定
	 * @param responseBean
	 * @param user
	 * @param parameter
	 * @return
	 */
	private ResponseBean checkWX(ResponseBean responseBean, TaUser user, String parameter) {
		// 检验用户状态
		iTaUserService.checkBlacklistStatusUser(user);

		// 检验是否关联了微信
		String userOpenid = user.getOpenid();
		if (StringUtils.isNotBlank(userOpenid)) {
			responseBean.addError("已关联了微信账号!");
			return responseBean;
		}

		JSONObject jsonObject = JSONObject.parseObject(parameter);
		logger.info("绑定的微信数据是：{}", parameter);

		String openid = jsonObject.getString("openid");
		if (StringUtils.isBlank(openid)) {
			throw new WisdomException("openid 参数缺失！");
		}
		String nickname = jsonObject.getString("nickname");
		try {
			nickname = new String(nickname.getBytes("ISO-8859-1"), "UTF-8");
			logger.info("解决微信昵称乱码后的昵称：{}", nickname);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}

		// 微信头像
		String headimgurl = jsonObject.getString("headimgurl");
		// 用户头像为空的时候，并且微信头像不为空的时候，就把微信头像设置为用户头像
		if (StringUtils.isBlank(user.getHeadPortrait()) && StringUtils.isNotBlank(headimgurl)) {
			user.setHeadPortrait(headimgurl);
		}

		user.setOpenid(openid);
		user.setNickname(nickname);

		// 更新用户信息
		taUserMapper.updateByPrimaryKeySelective(user);

		TaUserVO userVO = new TaUserVO();
		BeanTools.copyProperties(user, userVO);

		responseBean.addSuccess(userVO);
		return responseBean;
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public ResponseBean register(String parameter, HttpServletRequest request) {
		ResponseBean response = new ResponseBean();

		JSONObject jsonObject = JSONObject.parseObject(parameter);
		TaUser user = jsonObject.toJavaObject(TaUser.class);

		Map<String,Object> map = Maps.newHashMap();
		map.put("loginName",user.getLoginName());
		TaUser currentUser = taUserMapper.selectByLoginName(map);
		if (null != currentUser) {
			response.addError("手机号已被注册");
			return response;
		}

		String code = jsonObject.getString("code");

		// 校验手机号 和验证码
		iCode.checkPhoneAndCode(user.getLoginName(), code);

		// 开始注册
		user.setCreateDate(new Date());
		user.setUpdateDate(new Date());
		user.setStatus("1");
		user.setAcceptAgreementStatus("1");
		user.setUserName(user.getLoginName());
		String userName = jsonObject.getString("userName");
		if (StringUtils.isNotBlank(userName)) {
			user.setUserName(userName);
		}
		user.setRemark("这是系统自动注册!");
		user.setVerifyStatus("0");
		user.setFaceStatus("0");
		taUserMapper.insertSelective(user);

		user.setCreateUser(user.getId());
		user.setUpdateUser(user.getId());

		// 这里设置为null，因为在上面的 jsonObject.toJavaObject 装换的时候，自动的吧openid设置到这个user对象了
		// 下面的校验微信绑定时候，会把openid设置上去的
		user.setOpenid(null);

		// 更新
		taUserMapper.updateByPrimaryKeySelective(user);

		// 如果是 普通注册 就把用户数据返回出去
		TaUserVO userVO = new TaUserVO();
		BeanTools.copyProperties(user, userVO);
		// 刚注册的用户，跳转到绑定房产页面
		response.addError(UserVerifyEnum.NO_AUDIT_REAL_ESTATE.getMsg(), userVO, loginCodePerproties.getLoginCode().get(UserVerifyEnum.NO_AUDIT_REAL_ESTATE.getCode()) + "&token=" + request.getSession().getId());

		/**
		 * 这里是因为 手机号注册 和 社交登录的手机号注册，公用的一个接口，所以有 openid 的时候，表示是微信那边的社交登录
		 * 否则就是普通的 手机号注册
		 */
		String openid = jsonObject.getString("openid");
		if (StringUtils.isNotBlank(openid)) {
			// 检验微信绑定
			response = checkWX(response, user, parameter);
		}

		return response;
	}


	@Override
	public ResponseBean unbundlingWX(UserElement userElement) {
		ResponseBean responseBean = new ResponseBean();
		TaUser taUser = taUserMapper.selectByPrimaryKey(userElement.getId());
		taUser.setOpenid("");
		taUser.setNickname("");
		taUserMapper.updateByPrimaryKeySelective(taUser);

		responseBean.addSuccess("操作成功！");
		return responseBean;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public ResponseBean bundlingWX(UserElement userElement, String wxcode) {
		ResponseBean responseBean = new ResponseBean();

		OauthGetTokenResponse codeResponse = getOauthGetTokenResponse(wxcode);
		String openId = codeResponse.getOpenid();
		logger.info("获取到wxcode:" + wxcode + " 获取到的openid: " + openId + "accesstoken: " + codeResponse.getAccessToken());

		TaUser userOpenId = taUserMapper.getByOpenId(openId);
		if (null != userOpenId) {
			responseBean.addError("此微信号已绑定账户，请先使用微信登录解绑！");
			return responseBean;
		}

		String userInfo = getWXuserInfo(codeResponse.getAccessToken(), openId);
		JSONObject userInfoJSON = JSONObject.parseObject(userInfo);
		String nickname = userInfoJSON.getString("nickname");
		// 微信头像
		String headimgurl = userInfoJSON.getString("headimgurl");
		try {
			nickname = new String(nickname.getBytes("ISO-8859-1"), "UTF-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		TaUser taUser = taUserMapper.selectByPrimaryKey(userElement.getId());
		// 当用户头像为空的时候，并且微信头像不为空的时候，就把微信头像设置为用户头像
		if (StringUtils.isBlank(taUser.getHeadPortrait()) && StringUtils.isNotBlank(headimgurl)) {
			taUser.setHeadPortrait(headimgurl);
		}
		taUser.setOpenid(openId);
		taUser.setNickname(nickname);
		taUserMapper.updateByPrimaryKeySelective(taUser);

		responseBean.addSuccess("操作成功!");
		return responseBean;
	}
}
