package com.dora.service.impl;

import com.dora.service.WeChatAccessTokenService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;

import java.util.concurrent.TimeUnit;

/**
 * 微信AccessToken服务实现
 * 
 * @author dora
 * @date 2024/12/01
 */
@Slf4j
@Service
public class WeChatAccessTokenServiceImpl implements WeChatAccessTokenService {
    
    private final RedisTemplate<String, String> redisTemplate;
    
    @Value("${wx.mp.appid}")
    private String appId;
    
    @Value("${wx.mp.secret}")
    private String appSecret;
    
    private static final String ACCESS_TOKEN_KEY = "wechat:access_token";
    private static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
    
    public WeChatAccessTokenServiceImpl(RedisTemplate<String, String> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }
    
    @Override
    public String getAccessToken() {
        // 先从Redis获取
        String cachedToken = redisTemplate.opsForValue().get(ACCESS_TOKEN_KEY);
        if (StringUtils.hasText(cachedToken)) {
            return cachedToken;
        }
        
        // Redis中没有，重新获取
        return refreshAccessToken();
    }
    
    @Override
    @Retryable(value = {Exception.class}, maxAttempts = 3, backoff = @Backoff(delay = 2000))
    public String refreshAccessToken() {
        try {
            String url = String.format(ACCESS_TOKEN_URL, appId, appSecret);
            
            RestTemplate restTemplate = new RestTemplate();
            String response = restTemplate.getForObject(url, String.class);
            
            JSONObject jsonObject = JSON.parseObject(response);
            
            if (jsonObject.containsKey("errcode")) {
                String errorMsg = "获取AccessToken失败: " + jsonObject.getString("errmsg");
                log.error(errorMsg);
                throw new RuntimeException(errorMsg);
            }
            
            String accessToken = jsonObject.getString("access_token");
            Integer expiresIn = jsonObject.getInteger("expires_in");
            
            // 存储到Redis，提前5分钟过期
            redisTemplate.opsForValue().set(ACCESS_TOKEN_KEY, accessToken, 
                    expiresIn - 300, TimeUnit.SECONDS);
            
            log.info("AccessToken刷新成功，有效期: {}秒", expiresIn);
            return accessToken;
            
        } catch (Exception e) {
            log.error("刷新AccessToken失败", e);
            throw new RuntimeException("刷新AccessToken失败: " + e.getMessage());
        }
    }
    
    @Override
    public boolean isTokenValid(String token) {
        if (!StringUtils.hasText(token)) {
            return false;
        }
        
        try {
            // 简单验证：检查token是否在Redis中存在
            String cachedToken = redisTemplate.opsForValue().get(ACCESS_TOKEN_KEY);
            return token.equals(cachedToken);
        } catch (Exception e) {
            log.error("验证AccessToken失败", e);
            return false;
        }
    }
}
