package com.slodon.bbc.starter.thirdParty.client;

import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.slodon.b2b2c.core.exception.MallException;
import com.slodon.b2b2c.core.util.StringUtil;
import com.slodon.bbc.starter.thirdParty.constant.ThirdPartyConst;
import com.slodon.bbc.starter.thirdParty.entity.SlodonThirdPartyQrCodeRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.ui.ModelMap;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.util.concurrent.TimeUnit;

/**
 * 微信
 */
@Slf4j
public class WxClient implements ThirdPartyBaseClient {

    /**
     * 获取二维码
     * https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/qr-code/wxacode.getUnlimited.html
     *
     * @param stringRedisTemplate redis操作工具
     * @param qrCodeRequest       业务参数
     * @return 二维码图片
     */
    @Override
    public BufferedImage getQrCode(StringRedisTemplate stringRedisTemplate, SlodonThirdPartyQrCodeRequest qrCodeRequest) throws Exception {
        //获取凭证，优先使用缓存
        String access_token = stringRedisTemplate.opsForValue().get(ThirdPartyConst.REDIS_ACCESS_TOKEN_KEY_WX);
        if (StringUtils.isEmpty(access_token)) {
            //缓存不存在或已过期，重新获取并缓存
            access_token = this.getAccessToken(stringRedisTemplate);
            //缓存1小时
            stringRedisTemplate.opsForValue().set(ThirdPartyConst.REDIS_ACCESS_TOKEN_KEY_WX, access_token, 1L, TimeUnit.HOURS);
        }

        String qrUrl = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + access_token;
        //构造json参数
        ModelMap modelMap = new ModelMap();
        if (!CollectionUtils.isEmpty(qrCodeRequest.getParams())) {
            StringBuilder params = new StringBuilder();
            qrCodeRequest.getParams().forEach((k, v) -> {
                params.append(",").append(v);
            });
            modelMap.put("scene", params.toString().substring(1));
        }
        modelMap.put("width", 60);
        //需要小程序发布成功才能加此代码
        modelMap.put("page", qrCodeRequest.getPage());
        ModelMap color = new ModelMap();
        color.put("r", 0);
        color.put("g", 0);
        color.put("b", 0);
        modelMap.put("line_color", color);

        HttpResponse execute = HttpUtil.createPost(qrUrl).body(JSON.toJSONString(modelMap)).execute();

        if (!execute.isOk()) {
            //请求失败
            log.error("生成微信二维码失败：" + execute.body());
            throw new MallException("小程序维护中，请稍后再试");
        }

        BufferedImage bufferedImage = ImageIO.read(execute.bodyStream());
        if (bufferedImage == null) {
            log.error("生成微信二维码失败：" + execute.body());
            throw new MallException("小程序维护中，请稍后再试");
        }

        return bufferedImage;
    }

    /**
     * 获取access_token，失效时间为2个小时
     *
     * @param stringRedisTemplate redis操作工具
     * @return access_token
     */
    private String getAccessToken(StringRedisTemplate stringRedisTemplate) {
        //获取access_token地址
        String accessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token";
        String appid = stringRedisTemplate.opsForValue().get("login_wx_mini_appid");
        String secret = stringRedisTemplate.opsForValue().get("login_wx_mini_appsecret");
        ModelMap modelMap = new ModelMap();
        modelMap.put("appid", appid);
        modelMap.put("secret", secret);
        modelMap.put("grant_type", "client_credential");
        String resp = HttpUtil.get(accessTokenUrl, modelMap);
        JSONObject respJson = JSON.parseObject(resp);

        //请求失败格式 {"errcode":40013,"errmsg":"invalid appid rid: 61712877-77f549e7-2c4e7182"}
        //成功格式 {"access_token":"","expires_in":7200}
        if (!StringUtil.isNullOrZero(respJson.getInteger("errcode"))) {
            //请求失败
            log.error("获取微信小程序二维码失败：" + respJson.getString("errmsg"));
            throw new MallException("小程序维护中，请稍后再试");
        }
        //请求成功
        return respJson.getString("access_token");
    }
}
