package com.easyproject.common.utils.wx;

import cn.hutool.core.convert.ConvertException;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONException;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.easyproject.common.config.WxAppletConfig;
import com.easyproject.common.constant.CacheConstants;
import com.easyproject.common.core.redis.RedisCache;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.Duration;
import java.util.concurrent.TimeUnit;

/**
 * 方法说明: 微信小程序请求工具类
 *
 * @param
 * @author java-101
 * @return
 * @date 2025-04-15 21:27:53
 */
@Slf4j
@Component
public class WxAppletNotifyUtils {

    @Resource
    private WxAppletConfig wxAppletConfig;
    @Resource
    private RedisCache redisCache;

    /**
     * 获取微信access_token
     */
    private static final String tokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
    /**
     * 获取加密URLLink  获取小程序 URL Link，适用于短信、邮件、网页、微信内等拉起小程序的业务场景
     */
    private static final String linkUrl = "https://api.weixin.qq.com/wxa/generate_urllink?access_token=ACCESS_TOKEN";
    /**
     * 获获取ShortLink  适用于微信内拉起小程序的业务场景
     */
    private static final String shortUrl = "https://api.weixin.qq.com/wxa/genwxashortlink?access_token=ACCESS_TOKEN";


    /**
     * 方法说明: 生成小程序跳转短链 URLLink 外部使用
     *
     * @param path  小程序页面路径 为NULL 会跳转小程序主页
     * @param query 与前端商量，携带的参数
     * @param days  指定失效天数，最多30
     * @return 获取加密URLLink
     * @author java-101
     * @date 2025-04-15 21:38:15
     */
    public String getWxAppletUrlLink(String path, String query, Integer days) {
        String link = null;
        JSONObject jsonObject = null;
        try {
            String accessToken = getAccessToken();
            String url = linkUrl.replace("ACCESS_TOKEN", accessToken);
            JSONObject body = JSONUtil.createObj();
            body.putOpt("path", path);
            body.putOpt("query", query);

            //链接过期类型：0时间戳 1间隔天数
            body.putOpt("expire_type", 1);

            //指定失效天数，最多30
            days = (days == null || days > 30) ? 30 : days;
            body.putOpt("expire_interval", days);

            body.putOpt("env_version", wxAppletConfig.getEnvVersion()); //小程序版本，正式版为 "release"，体验版为"trial"，开发版为"develop"
            String post = HttpUtil.post(url, body.toJSONString(2));
            jsonObject = JSONUtil.parseObj(post);
            if (jsonObject.get("errcode", Integer.class, false) != 0) {
                log.error("获取小程序 URLLink 链接失败，编码：{}，错误信息：{}" , jsonObject.get("errcode", Integer.class, false), jsonObject.get("errmsg", String.class, false));
            } else {
                link = jsonObject.get("url_link", String.class, false);
            }
        } catch (JSONException e) {
            log.error("获取小程序 URLLink 链接，异常：{}", e.getMessage());
            throw new RuntimeException(e);
        }
        return link;
    }


    /**
     * 方法说明: 生成小程序跳转短链 ShortLink 内部使用
     *
     * @param page_url     通过 Short Link 进入的小程序页面路径，可携带？code=xx参数，目前固定：pages/index/index
     * @param page_title   页面标题，不能包含违法信息，超过20字符会用... 截断代替
     * @param is_permanent 短期有效：false，永久有效：true 默认 false
     * @return 获取加密URLLink
     * @author java-101
     * @date 2025-04-15 21:38:15
     */
    public String getWxAppletShortLink(String page_url, String page_title, boolean is_permanent) {
        String link = null;
        JSONObject jsonObject = null;
        try {
            String accessToken = getAccessToken();
            String url = shortUrl.replace("ACCESS_TOKEN", accessToken);
            JSONObject body = JSONUtil.createObj();
            body.putOpt("page_url", page_url);
            body.putOpt("page_title", page_title);
            body.putOpt("is_permanent", is_permanent);
            String post = HttpUtil.post(url, body.toJSONString(2));
            jsonObject = JSONUtil.parseObj(post);
            if (jsonObject.get("errcode", Integer.class, false) != 0) {
                log.error("获取小程序 ShortLink 链接失败，编码：{}，错误信息：{}" , jsonObject.get("errcode", Integer.class, false), jsonObject.get("errmsg", String.class, false));
            } else {
                link = jsonObject.get("link", String.class, false);
            }
        } catch (RuntimeException e) {
            log.error("获取小程序 ShortLink 链接，异常：{}", e.getMessage());
            throw new RuntimeException(e);
        }
        return link;
    }

    /**
     * 方法说明: 获取微信小程序用户access_token
     *
     * @param
     * @return
     * @author java-101
     * @date 2025-04-15 21:51:45
     */
    public String getAccessToken() {
        String token = null;
        try {
            //缓存存在token
            if (redisCache.hasKey(CacheConstants.APPLET_ACCESS_TOKEN_KEY)) {
                //redis直接获取小程序token
                token = redisCache.getCacheObject(CacheConstants.APPLET_ACCESS_TOKEN_KEY);
            } else {
                //拼接url
                String url = tokenUrl.replace("APPID", wxAppletConfig.getAppId()).replace("APPSECRET", wxAppletConfig.getAppSecret());
                //get请求
                String result = HttpUtil.get(url);
                //解析结果
                JSONObject jsonObject = JSONUtil.parseObj(result);
                //get AccessToken
                token = jsonObject.get("access_token", String.class, true);
                //get 过期时间 单位秒
                Long expiresIn = jsonObject.get("expires_in", Long.class, true);
                //存入redis并减少60秒
                redisCache.setCacheObject(CacheConstants.APPLET_ACCESS_TOKEN_KEY, token, Integer.valueOf(String.valueOf(expiresIn - 60)), TimeUnit.SECONDS);
            }
        } catch (ConvertException e) {
            log.error("获取小程序 access_token 失败：{}", e.getMessage());
            throw new RuntimeException(e);
        }
        return token;
    }
}
