package com.zt.plat.module.contractorder.util;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

/**
 * ePlat共享服务调用工具类
 */
@Slf4j
@Configuration
@Component
public class ShareServiceUtil {
    private static final String SHARE_TOKEN_KEY = "eplat:cache:shareToken";
    private static final String SHARE_REFRESH_TOKEN_KEY = "eplat:cache:shareRefreshToken";
    private static final int TOKEN_TIME_OUT = 5000; // token过期时间，默认7200秒，这里设置建议小一些，如7000秒

    @Value("${eplat.share.urlPrex}")
    private String urlPrex;
    @Value("${eplat.share.clientId}")
    private String clientId;
    @Value("${eplat.share.clientSecret}")
    private String clientSecret;


    @Resource
    private RestTemplate restTemplate;
    @Resource
    private RedisUtil redisUtil;


    /**
     * ePlat共享服务调用
     * @param serviceNo 服务号
     * @param request 请求json字符串
     * @return 调用结果
     */
    public String callShareService(String serviceNo, String request) {
        String url = String.format("%s/service/%s", urlPrex, serviceNo);
        log.info("ePlat共享服务调用url:[" + url + "]，request:[" + request + "]");
        String token = generateToken();
        log.info("目标token：" + token);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        headers.add("Xplat-Token", token);
        HttpEntity<String> entity = new HttpEntity<>(request, headers);
        ResponseEntity<String> result = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
        return result.getBody();
    }

    private String generateToken() {
        // 先从redis中获取未过期token
        String token = (String) redisUtil.get(SHARE_TOKEN_KEY);
        if (token == null) {
            synchronized (ShareServiceUtil.class) {
                token = (String) redisUtil.get(SHARE_TOKEN_KEY);
                if (token == null) {
                    try {
                        token = refreshToken();
                    } catch (Exception e) {
                        log.warn("生成token出错，可能刷新token有问题，重新尝试下", e);
                        redisUtil.del(SHARE_REFRESH_TOKEN_KEY);
                        token = refreshToken();
                    }
                }
            }
        }
        return token;
    }

    private String refreshToken() {
        // 先从redis中获取未过期的刷新token
        String refreshToken = (String) redisUtil.get(SHARE_REFRESH_TOKEN_KEY);
        if (refreshToken == null) {
            // 重新创建token和刷新token
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
            // 构造form表单
            MultiValueMap<String, String> paramsMap = new LinkedMultiValueMap<>();
            paramsMap.set("client_id", clientId);
            paramsMap.set("client_secret", clientSecret);
            paramsMap.set("grant_type", "client_credentials");
            paramsMap.set("scope", "read");
            String url = String.format("%s/eplat/oauth/token", urlPrex);
            // 构造请求的实体。包含body和headers的内容
            HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(paramsMap, headers);
            log.info("获取token调用url:[" + url + "]，request:[" + paramsMap + "]");
            ResponseEntity<String> result = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
            JSONObject json = JSONUtil.parseObj(result.getBody());
            String accessToken = json.getStr("access_token");
            refreshToken = json.getStr("refresh_token");
            // 缓存token、刷新token(刷新token过期时间为2倍token过期时间）
            redisUtil.set(SHARE_TOKEN_KEY, accessToken, TOKEN_TIME_OUT);
            redisUtil.set(SHARE_REFRESH_TOKEN_KEY, refreshToken, TOKEN_TIME_OUT * 2);
            return accessToken;
        } else {
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
            // 构造form表单
            MultiValueMap<String, String> paramsMap = new LinkedMultiValueMap<>();
            paramsMap.set("client_id", clientId);
            paramsMap.set("client_secret", clientSecret);
            paramsMap.set("grant_type", "refresh_token");
            paramsMap.set("refresh_token", refreshToken);
            String url = String.format("%s/eplat/oauth/token", urlPrex);
            // 构造请求的实体。包含body和headers的内容
            HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(paramsMap, headers);
            log.info("刷新token调用url:[" + url + "]，request:[" + paramsMap + "]");
            ResponseEntity<String> result = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
            JSONObject json = JSONUtil.parseObj(result.getBody());
            String accessToken = json.getStr("access_token");
            refreshToken = json.getStr("refresh_token");
            // 缓存token、刷新token(刷新token过期时间为2倍token过期时间）
            redisUtil.set(SHARE_TOKEN_KEY, accessToken, TOKEN_TIME_OUT);
            redisUtil.set(SHARE_REFRESH_TOKEN_KEY, refreshToken, TOKEN_TIME_OUT * 2);
            return accessToken;
        }
    }
}
