package com.gxwebsoft;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import okhttp3.*;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.time.Instant;
import java.util.concurrent.atomic.AtomicReference;

@Service
public class WxDev {

  @Value("${wechat.appid}")
  private String appId;
  @Value("${wechat.secret}")
  private String secret;

  private final StringRedisTemplate redisTemplate;

  private final OkHttpClient http = new OkHttpClient();
  private final ObjectMapper om = new ObjectMapper();

  /** 简单本地缓存 access_token（生产建议放 Redis） */
  private final AtomicReference<String> cachedToken = new AtomicReference<>();
  private volatile long tokenExpireEpoch = 0L; // 过期的 epoch 秒

  public WxDev(StringRedisTemplate redisTemplate) {
    this.redisTemplate = redisTemplate;
  }

  /** 获取/刷新 access_token */
  public String getAccessToken() throws IOException {
    long now = Instant.now().getEpochSecond();
    System.out.println("cachedToken.get = " + cachedToken.get());
    if (cachedToken.get() != null && now < tokenExpireEpoch - 60) {
      return cachedToken.get();
    }
    HttpUrl url = HttpUrl.parse("https://api.weixin.qq.com/cgi-bin/token")
      .newBuilder()
      .addQueryParameter("grant_type", "client_credential")
      .addQueryParameter("appid", "wx51962d6ac21f2ed2")
      .addQueryParameter("secret", "d821f98de8a6c1ba7bc7e0ee84bcbc8e")
      .build();
    Request req = new Request.Builder().url(url).get().build();
    try (Response resp = http.newCall(req).execute()) {
      String body = resp.body().string();
      JsonNode json = om.readTree(body);
      if (json.has("access_token")) {
        String token = json.get("access_token").asText();
        int expiresIn = json.get("expires_in").asInt(7200);
        System.out.println("token1 = " + token);
        cachedToken.set(token);
        tokenExpireEpoch = now + expiresIn;
        return token;
      } else {
        throw new IOException("Get access_token failed: " + body);
      }
    }
  }

  /** 调用 getwxacodeunlimit，返回图片二进制 */
  public byte[] getUnlimitedCode(String scene, String page, Integer width,
                                 Boolean isHyaline, String envVersion) throws IOException {
    String accessToken = getAccessToken();
    System.out.println("accessToken = " + accessToken);
    HttpUrl url = HttpUrl.parse("https://api.weixin.qq.com/wxa/getwxacodeunlimit")
      .newBuilder()
      .addQueryParameter("access_token", accessToken)
      .build();

    // 构造请求 JSON
    // 注意：scene 仅支持可见字符，长度上限 32，尽量 URL-safe（字母数字下划线等）
    // page 必须是已发布小程序内的路径（不带开头斜杠也可）
    var root = om.createObjectNode();
    root.put("scene", scene);
    if (page != null) root.put("page", page);
    if (width != null) root.put("width", width); // 默认 430，建议 280~1280
    if (isHyaline != null) root.put("is_hyaline", isHyaline);
    if (envVersion != null) root.put("env_version", envVersion); // release/trial/develop

    RequestBody reqBody = RequestBody.create(
      root.toString(), MediaType.parse("application/json; charset=utf-8"));
    Request req = new Request.Builder().url(url).post(reqBody).build();

    try (Response resp = http.newCall(req).execute()) {
      if (!resp.isSuccessful()) {
        throw new IOException("HTTP " + resp.code() + " calling getwxacodeunlimit");
      }
      MediaType ct = resp.body().contentType();
      byte[] bytes = resp.body().bytes();
      // 微信出错时返回 JSON，需要识别一下
      if (ct != null && ct.subtype() != null && ct.subtype().contains("json")) {
        String err = new String(bytes);
        throw new IOException("WeChat error: " + err);
      }
      return bytes; // 成功就是图片二进制（PNG）
    }
  }

  @Test
  public void getQrCode() throws IOException {
    final byte[] test = getUnlimitedCode("register", "pages/index/index",180,false,"develop");
    System.out.println("test = " + test);
  }
}
