package com.boco.nbd.wios.wx.weixin;

import com.boco.nbd.cams.core.constant.CamsConstant;
import com.ihidea.component.cache.redis.RedisClient;
import com.ihidea.core.support.exception.ServiceException;
import com.ihidea.core.util.HttpClientUtils;
import com.ihidea.core.util.JSONUtilsEx;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.text.MessageFormat;
import java.util.Map;

/**
 * 微信公众号帮助类
 *
 * @author Kevin
 */
@Component
public class WeixinHelper {

    private static Log logger = LogFactory.getLog(WeixinHelper.class);

    /**
     * 通过code换取网页授权access_token
     */
    private static final String SNS_API_URL_GET_ACCESS_TOKEN = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={0}&secret={1}&code={2}&grant_type=authorization_code";

    // 获取调用接口基础access_token
    protected static final String GET_ACCESS_TOKEN = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}";

    // 获取票据
    protected static final String WX_JSAPI_TICKET = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={0}&type=jsapi";

    protected static final String WX_MEDIA_GET = "https://api.weixin.qq.com/cgi-bin/media/get?access_token={0}&media_id={1}";

    private static String weixinAppId;

    @Value("${weixin.appId}")
    public void setWeixinAppId(String appId) {
        WeixinHelper.weixinAppId = appId;
    }

    private static String weixinAppSecret;

    @Value("${weixin.appSecret}")
    public void setWeixinAppSecret(String appSecret) {
        WeixinHelper.weixinAppSecret = appSecret;
    }

    /**
     * 通过code换取网页授权access_token
     *
     * @param appid  公众号的唯一标识
     * @param secret 公众号的appsecret
     * @param code   获取的code参数
     * @return AccessToken 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
     * @Title: getAccessTokenByCode
     * @Description: 通过code换取网页授权access_token, 此access_token与基础支持的access_token不同
     * @see AccessToken
     */
    public static AccessToken getAccessTokenByCode(String appid, String secret, String code) {
        String url = MessageFormat.format(SNS_API_URL_GET_ACCESS_TOKEN, appid, secret, code);
        String result = HttpClientUtils.get(url, null, CamsConstant.UTF_8, CamsConstant.UTF_8);
        logger.debug("获取微信openId返回:" + result);
        AccessToken token = JSONUtilsEx.deserialize(result, AccessToken.class);
        return token;
    }

    public static String getOpenIdByCode(String code) {
        AccessToken accessToken = getAccessTokenByCode(weixinAppId, weixinAppSecret, code);
        return accessToken != null ? accessToken.getOpenid() : null;
    }

    public static String getAccessToken(String appid, String secret) {
        // String accessToken="";
        String accessToken = RedisClient.get("wxAccessTokenCache_" + appid, String.class);

        if (StringUtils.isEmpty(accessToken)) {
            String url = MessageFormat.format(GET_ACCESS_TOKEN, appid, secret);
            String tokenJson = HttpClientUtils.get(url, null, CamsConstant.UTF_8, CamsConstant.UTF_8);
            logger.debug("请求accessToken返回:" + tokenJson);
            AccessToken token = JSONUtilsEx.deserialize(tokenJson, AccessToken.class);
            if (token != null && StringUtils.isNotEmpty(token.getAccess_token())) {
                RedisClient.put("wxAccessTokenCache_" + appid, token.getAccess_token(), 5400);
                accessToken = token.getAccess_token();
            } else {
                throw new ServiceException("获取微信access_token发生异常");
            }
        }

        return accessToken;
    }

    public static String getJsapiTicket(String appid, String secret) {
        String accessToken = getAccessToken(appid, secret);
        String jsapiTicket = RedisClient.get("wxJsapiTicketCache_" + appid, String.class);

        if (StringUtils.isEmpty(jsapiTicket)) {
            String url = MessageFormat.format(WX_JSAPI_TICKET, accessToken);
            JsapiTicket ticket = JSONUtilsEx.deserialize(HttpClientUtils.get(url, null, CamsConstant.UTF_8, CamsConstant.UTF_8), JsapiTicket.class);
            if (ticket != null && StringUtils.isNotEmpty(ticket.getTicket())) {
                RedisClient.put("wxJsapiTicketCache_" + appid, ticket.getTicket(), 5400);
                jsapiTicket = ticket.getTicket();
            } else {
                if (ticket.getErrcode() != null && ticket.getErrcode() == 42001) {
                    RedisClient.remove("wxAccessTokenCache_" + appid);
                    return getJsapiTicket(appid, secret);
                }
                throw new ServiceException("获取微信jsapiTicket发生异常");
            }
        }

        return jsapiTicket;
    }

    public static byte[] getMediaContent(String mediaId) {
        String accessToken = getAccessToken(weixinAppId, weixinAppSecret);

        String url = MessageFormat.format(WX_MEDIA_GET, accessToken, mediaId);
        byte[] result = HttpClientUtils.getContent(url, null, CamsConstant.UTF_8);
        String resultStr = new String(result);
        if (StringUtils.contains(resultStr, "errcode")) {
            Map<String, String> resultMap = JSONUtilsEx.deserialize(resultStr, Map.class);
            throw new ServiceException(resultMap.get("errmsg"));
        }
        return result;
    }
}