package com.gxwebsoft.common.system.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.common.core.exception.BusinessException;
import com.gxwebsoft.common.core.utils.RedisUtil;
import com.gxwebsoft.common.system.service.WxMiniappAccessTokenService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

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

import static com.gxwebsoft.common.core.constants.RedisConstants.ACCESS_TOKEN_KEY;
import static com.gxwebsoft.common.core.constants.RedisConstants.MP_WX_KEY;

/**
 * 微信小程序 access_token 获取实现（按租户）。
 *
 * <p>复用现有缓存结构：
 * <ul>
 *   <li>小程序配置：Redis key = {@code mp-weixin:{tenantId}}，value 为 JSON，包含 appId/appSecret</li>
 *   <li>access_token：Redis key = {@code access-token:{tenantId}}，value 为微信返回的 JSON 字符串</li>
 * </ul>
 * </p>
 */
@Slf4j
@Service
public class WxMiniappAccessTokenServiceImpl implements WxMiniappAccessTokenService {

    @Resource
    private RedisUtil redisUtil;

    @Override
    public String getAccessToken(Integer tenantId) {
        if (tenantId == null) {
            throw new BusinessException("tenantId 不能为空");
        }

        final String tokenCacheKey = ACCESS_TOKEN_KEY + ":" + tenantId;

        // 1) 优先从缓存取（兼容 JSON 或纯字符串 token 的历史格式）
        String cachedValue = redisUtil.get(tokenCacheKey);
        if (StrUtil.isNotBlank(cachedValue)) {
            try {
                JSONObject cachedJson = JSON.parseObject(cachedValue);
                String accessToken = cachedJson.getString("access_token");
                if (StrUtil.isNotBlank(accessToken)) {
                    return accessToken;
                }
            } catch (Exception ignore) {
                // 旧格式：直接存 token
                return cachedValue;
            }
        }

        // 2) 缓存没有则从租户配置获取 appId/appSecret
        final String wxConfigKey = MP_WX_KEY + tenantId;
        final String wxConfigValue = redisUtil.get(wxConfigKey);
        if (StrUtil.isBlank(wxConfigValue)) {
            throw new BusinessException("未找到微信小程序配置，请检查缓存key: " + wxConfigKey);
        }

        JSONObject wxConfig;
        try {
            wxConfig = JSON.parseObject(wxConfigValue);
        } catch (Exception e) {
            throw new BusinessException("微信小程序配置格式错误: " + e.getMessage());
        }

        final String appId = wxConfig.getString("appId");
        final String appSecret = wxConfig.getString("appSecret");
        if (StrUtil.isBlank(appId) || StrUtil.isBlank(appSecret)) {
            throw new BusinessException("微信小程序配置不完整(appId/appSecret)");
        }

        // 3) 调用微信接口获取 token
        final String apiUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential"
                + "&appid=" + appId + "&secret=" + appSecret;
        String result = HttpUtil.get(apiUrl);

        JSONObject json = JSON.parseObject(result);
        if (json.containsKey("errcode") && json.getIntValue("errcode") != 0) {
            Integer errcode = json.getInteger("errcode");
            String errmsg = json.getString("errmsg");
            throw new BusinessException("获取小程序access_token失败: " + errmsg + " (errcode: " + errcode + ")");
        }

        String accessToken = json.getString("access_token");
        Integer expiresIn = json.getInteger("expires_in");
        if (StrUtil.isBlank(accessToken)) {
            throw new BusinessException("获取小程序access_token失败: access_token为空");
        }

        // 4) 缓存微信原始 JSON（与现有实现保持一致），提前5分钟过期
        long ttlSeconds = 7000L;
        if (expiresIn != null && expiresIn > 300) {
            ttlSeconds = expiresIn - 300L;
        }
        redisUtil.set(tokenCacheKey, result, ttlSeconds, TimeUnit.SECONDS);

        log.info("获取小程序access_token成功 - tenantId={}, ttlSeconds={}", tenantId, ttlSeconds);
        return accessToken;
    }
}

