package org.springblade.modules.system.service.impl;

import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.redis.cache.BladeRedis;
import org.springblade.modules.system.entity.User;
import org.springblade.modules.system.entity.UserInfo;
import org.springblade.modules.system.entity.UserWeChat;
import org.springblade.modules.system.mapper.UserWeChatMapper;
import org.springblade.modules.system.service.IUserWeChatService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

/**
 * Author pangqijun
 * Date 2022/11/8
 * Description
 */
@Slf4j
@Service
public class UserWeChatServiceImpl extends ServiceImpl<UserWeChatMapper, UserWeChat> implements IUserWeChatService {

	private final static String WX_AUTH_CODE2SESSION = "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code";
	private final static String WX_GET_ACCESS_TOKEN = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
	private final static String WX_GET_USER_PHONE_NUMBER = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=";
	private final static String WX_ACCESS_TOKEN_PREFIX = "wx:access:token";

	@Value("${v3.appIdxcx}")
	private String appId;
	@Value("${v3.appSecretxcx}")
	private String appSecret;
	@Autowired
	private BladeRedis bladeRedis;

	@Override
	public void saveUserInfo(UserInfo userInfo, String code) {
		User user = userInfo.getUser();
		log.info("userId:[{}], code:[{}]", user.getId(), code);
		String url = String.format(WX_AUTH_CODE2SESSION, appId, appSecret, code);
		log.info("url:[{}]", url);
		String result = HttpRequest.get(url).execute().body();
		log.info("微信登录凭证校验结果: [{}]", result);
		JSONObject jsonObject = JSON.parseObject(result);
		UserWeChat userWeChat = this.lambdaQuery().eq(UserWeChat::getUserId, user.getId()).one();
		if (userWeChat == null) {
			userWeChat = new UserWeChat();
			userWeChat.setUserId(user.getId());
		}
		userWeChat.setOpenId(jsonObject.getString("openid"));
		userWeChat.setUnionId(jsonObject.getString("unionid"));
		userWeChat.setSessionKey(jsonObject.getString("session_key"));
		this.saveOrUpdate(userWeChat);
		userInfo.setOpenId(userWeChat.getOpenId());
	}

	@Override
	public String getAccessToken() {
		Object o = bladeRedis.get(WX_ACCESS_TOKEN_PREFIX);
		if (o != null) {
			return (String) o;
		}
		String url = String.format(WX_GET_ACCESS_TOKEN, appId, appSecret);
		log.info("获取access_token, url:[{}]", url);
		String result = HttpRequest.get(url).execute().body();
		log.info("获取access_token: [{}]", result);
		JSONObject jsonObject = JSON.parseObject(result);
		Integer errcode = jsonObject.getInteger("errcode");
		if (errcode != null && errcode != 0) {
			throw new ServiceException("获取AccessToken异常");
		} else {
			String accessToken = jsonObject.getString("access_token");
			Long expiresIn = jsonObject.getLong("expires_in");
			bladeRedis.setEx(WX_ACCESS_TOKEN_PREFIX, accessToken, expiresIn);
			return accessToken;
		}
	}

	@Override
	public String getPhoneNumber(String code) {
		String accessToken = this.getAccessToken();
		Map<String, Object> paramMap = new HashMap<>();
		paramMap.put("code", code);
		String result = HttpRequest.post(WX_GET_USER_PHONE_NUMBER + accessToken).body(JSON.toJSONString(paramMap)).execute().body();
		log.info("微信获取用户手机号结果: [{}]", result);
		JSONObject jsonObject = JSON.parseObject(result);
		Integer errcode = jsonObject.getInteger("errcode");
		if (errcode != null && errcode != 0) {
			throw new ServiceException("微信获取用户手机号失败_" + errcode + ":" + jsonObject.getString("errmsg"));
		} else {
			return jsonObject.getJSONObject("phone_info").getString("phoneNumber");
		}
	}
}
