package cn.ey.biz.module.weaver.common;

import cn.ey.biz.common.exception.ErrorCode;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson2.JSON;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import javax.annotation.Resource;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import static cn.ey.biz.common.exception.util.ServiceExceptionUtil.exception;

@Slf4j
public class TokenGetter {

    @Value("${weaver.service.url}")
    String url;
    @Value("${weaver.token.timeout}")
    String timeout;
    @Resource
    StringRedisTemplate stringRedisTemplate;

    /**
     * 调用ecology注册接口,根据appid进行注册,将返回服务端公钥和Secret信息
     */
    private void registry(String appId){
        //获取当前系统RSA加密的公钥
        RSA rsa = new RSA();
        String publicKey = rsa.getPublicKeyBase64();
        //调用ECOLOGY系统接口进行注册
        String data = HttpRequest.post(url + "/api/ec/dev/auth/regist")
                .header("appid", appId)
                .header("cpk", publicKey)
                .timeout(5000)
                .execute().body();
        // 打印ECOLOGY响应信息
        RegistryResponse response = JSON.parseObject(data, RegistryResponse.class);
        if(response.status) {
            //ECOLOGY返回的系统公钥
            stringRedisTemplate.opsForValue().set(Constants.SERVER_PUBLIC_KEY+appId, response.getSpk());
            //ECOLOGY返回的系统密钥
            stringRedisTemplate.opsForValue().set(Constants.SERVER_SECRET_KEY+appId, response.getSecrit());
        }else{
            exception(new ErrorCode(-1, response.getErrmsg()));
        }
    }

    /**
     * 获取token信息
     */
    public String token(String appId) {
        String token = stringRedisTemplate.opsForValue().get(Constants.SERVER_TOKEN_KEY+appId);
        if(Objects.nonNull(token)){
            log.info("cache token:{}.", token);
            return token;
        }
        // 从系统缓存中获取ECOLOGY系统公钥和Secret信息
        String secret = stringRedisTemplate.opsForValue().get(Constants.SERVER_SECRET_KEY+appId);
        String spk    = stringRedisTemplate.opsForValue().get(Constants.SERVER_PUBLIC_KEY+appId);
        // 如果为空,说明还未进行注册,调用注册接口进行注册认证与数据更新
        if (Objects.isNull(secret) || Objects.isNull(spk)) {
            registry(appId);
            // 重新获取最新ECOLOGY系统公钥和Secret信息
            secret = stringRedisTemplate.opsForValue().get(Constants.SERVER_SECRET_KEY+appId);
            spk    = stringRedisTemplate.opsForValue().get(Constants.SERVER_PUBLIC_KEY+appId);
        }
        // 公钥加密,所以RSA对象私钥为null
        RSA rsa = new RSA(null, spk);
        //对秘钥进行加密传输，防止篡改数据
        String encryptSecret = rsa.encryptBase64(secret, CharsetUtil.CHARSET_UTF_8, KeyType.PublicKey);
        //调用ECOLOGY系统接口进行注册
        String data = HttpRequest.post(url + "/api/ec/dev/auth/applytoken")
                .header("appid", appId)
                .header("secret", encryptSecret)
                .header("time", timeout)
                .execute().body();
        log.info("weaver data:{}.", data);
        TokenResponse response = JSON.parseObject(data, TokenResponse.class);
        if(response.isStatus()){
            //ECOLOGY返回的token
            token = response.getToken();
            //为Token缓存设置过期时间
            stringRedisTemplate.opsForValue().set(Constants.SERVER_TOKEN_KEY+appId, token, Integer.parseInt(timeout), TimeUnit.MILLISECONDS);
        }else{
            throw exception(new ErrorCode(-1, response.getMsg()));
        }
        log.info("token:{}.", token);
        return token;
    }

    @Data
    static class RegistryResponse{
        boolean status;
        String spk;
        String secrit;
        String errmsg;
    }
    @Data
    static class TokenResponse{
        boolean status;
        String token;
        String msg;
    }

}
