package com.qs.mp.framework.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.qs.mp.common.core.redis.RedisCache;
import com.qs.mp.common.enums.ServerEnvEnum;
import com.qs.mp.common.exception.ServiceException;
import com.qs.mp.common.utils.DateUtils;
import com.qs.mp.common.utils.LogUtil;
import com.qs.mp.common.utils.StringUtils;
import com.qs.mp.common.utils.http.HttpUtils;
import com.qs.mp.common.utils.http.MpHttpRequestUtils;
import com.qs.mp.framework.domain.AppToken;
import com.qs.mp.framework.mapper.AppTokenMapper;
import com.qs.mp.framework.redis.RedisKey;
import com.qs.mp.framework.redis.RedisUtil;
import com.qs.mp.framework.service.IAppTokenService;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Service
public class AppTokenServiceImpl implements IAppTokenService {

  protected final Logger logger = LoggerFactory.getLogger(AppTokenServiceImpl.class);

  @Autowired
  private AppTokenMapper appTokenMapper;


  @Autowired
  private RedisCache redisCache;

  @Value(value = "${server.env}")
  private String env;

  @Override
  public AppToken selectByPrimaryKey(String appId) {
    return appTokenMapper.selectByPrimaryKey(appId);
  }

  @Override
  public String getAccessToken(String appId) {
    String cacheKey = RedisKey.build(RedisKey.WX_APP_TOKEN_KEY, appId);

    String resToken = "";
    Object object = redisCache.getCacheObject(cacheKey);
    if (null != object && object instanceof String) {
      resToken = String.valueOf(object);
    }
    if (StringUtils.isNotBlank(resToken)) {
      return resToken;
    }

    if (ServerEnvEnum.PROD.getCode().equals(env)) {
      AppToken token = selectByPrimaryKey(appId);
      if (null == token) {
        LogUtil.error(logger, "app_token记录不存在，appId:{0}", appId);
        throw new ServiceException();
      }

   // LogUtil.info(logger, "token: {0}", JSON.toJSONString(token));
    if (new Date().after(token.getExpireTimestamp())) {
        String res = wxGetAccessToken(appId, token.getAppSecret());
        if (StringUtils.isEmpty(res)) {
          LogUtil.error(logger, "获取access_token为空，appId:{0}, res:{1}", appId,
              res);
          throw new ServiceException();
        }
        JSONObject jsonObject = JSONObject.parseObject(res);
        String accessToken = jsonObject.getString("access_token");

        Integer expiresIn = jsonObject.getInteger("expires_in");
        if (StringUtils.isEmpty(accessToken)) {
          LogUtil.error(logger, "获取access_token为空，appId:{0}, res:{1}",
              appId, res);
          throw new ServiceException("access_token获取为空");
        }
        token.setAccessToken(accessToken);
        // 防止时间不同步，此处提前600s超时
        token.setExpireTimestamp(DateUtils.addSeconds(new Date(), expiresIn - 600));
        appTokenMapper.updateByPrimaryKeySelective(token);
      }
      resToken = token.getAccessToken();
    } else {
      // 线下环境，从生产环境获取
      String res = getAccessTokenFromProd(appId);
      JSONObject jsonObject = JSONObject.parseObject(res);
      int code = jsonObject.getInteger("code");
      if (code != 0) {
        LogUtil.error(logger, "获取accessToken失败，appId:{0},res:{1}",new Object[]{appId, res});
        throw new ServiceException("获取accessToken失败");
      }
      resToken = jsonObject.getString("data");
    }
    redisCache.setCacheObject(cacheKey, resToken, 1, TimeUnit.MINUTES);
    return resToken;
  }

  private String wxGetAccessToken(String appId, String appSecret) {
    String param = "appid=" + appId + "&secret=" + appSecret + "&grant_type=client_credential";
    String res = HttpUtils.sendGet("https://api.weixin.qq.com/cgi-bin/token", param);
    return res;

  }

  private String getAccessTokenFromProd(String appId) {
    String params = "{\"appId\":\"" + appId + "\"}";
    String url = "https://mp-api.51jiazhu.com/api/v1/mp/wx/getAccessToken?";
    String res = MpHttpRequestUtils.request(url, params);
    LogUtil.info(logger, "获取accessToken结果：" + res);
    return res;
  }

}
