package com.fs.wx.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.fs.wx.service.WeChatAuthService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Service
public class InMemoryWeChatAuthServiceImpl implements WeChatAuthService {

    private static final Logger log = LoggerFactory.getLogger(InMemoryWeChatAuthServiceImpl.class);
    private String cachedToken = null;
    private long expiryTime = 0; // Token 过期时间戳 (ms)

    @Value("${wx.miniapp.configs[0].appid}")
    private String appId;

    @Value("${wx.miniapp.configs[0].secret}")
    private String appSecret;

    private final String tokenUrlFormat = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";

    public InMemoryWeChatAuthServiceImpl() {
    }


    @Override
    public synchronized String getAccessToken(boolean forceRefresh) {
        long now = System.currentTimeMillis();
        if (!forceRefresh && cachedToken != null && now < expiryTime) {
            log.debug("Using cached access token.");
            return cachedToken;
        }

        if (StrUtil.hasBlank(appId, appSecret)) {
            log.error("appId或者appSecret不存在!");
            throw new RuntimeException("appId或者appSecret不存在!");
        }


        String url = String.format(tokenUrlFormat, appId, appSecret);
        log.info(url);
        HttpResponse httpResponse = null;
        String body = null;

        try {
            httpResponse = HttpRequest.get(url)
                    .timeout(5000)
                    .execute();

            body = httpResponse.body();

            if (!httpResponse.isOk()) {
                log.error("获取accessToken失败!. Status: {}, Body: {}", httpResponse.getStatus(), body);
                String errorMsg = parseErrorMsg(body);
                throw new RuntimeException("获取accessToken失败! Status: " + httpResponse.getStatus() + ", Message: " + errorMsg);
            }

            if (StrUtil.isBlank(body)) {
                log.error("获取accessToken失败!.  URL: {}", url);
                throw new RuntimeException("获取accessToken失败!");
            }

            JSONObject responseJson = JSONUtil.parseObj(body);

            if (responseJson.containsKey("access_token")) {
                cachedToken = responseJson.getStr("access_token");
                if(StrUtil.isBlank(cachedToken)){
                    log.error("获取accessToken失败!response: {}", body);
                    throw new RuntimeException("获取accessToken失败!");
                }

                long expiresInSeconds = responseJson.getLong("expires_in", 7200L);
                expiryTime = now + (expiresInSeconds - 300) * 1000;
                log.info("获取accessToken获取成功 {}",cachedToken);
                return cachedToken;
            } else {
                String errorMsg = responseJson.getStr("errmsg", "Unknown error: access_token missing in response");
                log.error("Failed to fetch access token, 'access_token' key missing. Response: {}", body);
                throw new RuntimeException("Failed to fetch access token: " + errorMsg);
            }
        } catch (Exception e) {
            log.error("Error fetching access token from URL: {}", url, e);
            throw new RuntimeException("Error fetching access token: " + e.getMessage(), e);
        }
    }

    private String parseErrorMsg(String jsonBody) {
        if (StrUtil.isBlank(jsonBody)) {
            return "返回为空!";
        }
        try {
            JSONObject json = JSONUtil.parseObj(jsonBody);
            return json.getStr("errmsg", "Unknown error in response body");
        } catch (Exception e) {
            return "返回解析失败!";
        }
    }
}
