package cn.reghao.tnb.auth.app.service;

import cn.reghao.jutil.jdk.security.RandomString;
import cn.reghao.jutil.jdk.security.RsaCryptor;
import cn.reghao.tnb.auth.api.dto.RsaPubkey;
import cn.reghao.tnb.auth.app.config.redis.RedisKeys;
import cn.reghao.tnb.auth.app.config.redis.ds.RedisString;
import org.springframework.stereotype.Service;

import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.Map;

/**
 * @author reghao
 * @date 2023-02-20 11:09:03
 */
@Service
public class PubkeyService {
    private final RedisString redisString;

    public PubkeyService(RedisString redisString) {
        this.redisString = redisString;
    }

    public RsaPubkey getPubkey() throws NoSuchAlgorithmException {
        String pubkey = redisString.get(RedisKeys.getRsaPubkeyKey());
        if (pubkey == null) {
            Map<String, String> rsaKeyPair = RsaCryptor.genKeyPair();
            String prikey = rsaKeyPair.get("prikey");
            pubkey = rsaKeyPair.get("pubkey");

            redisString.set(RedisKeys.getRsaPubkeyKey(), pubkey);
            redisString.set(RedisKeys.getRsaPrikeyKey(), prikey);
        }

        String r = RandomString.getString(16);
        long timeout = 300;
        redisString.setWithTimeout(RedisKeys.getPubkeyRKey(), r, timeout);
        return new RsaPubkey(pubkey, r);
    }

    public String decrypt(String cipherText) throws Exception {
        String prikey = redisString.get(RedisKeys.getRsaPrikeyKey());
        if (prikey == null) {
            String msg = "私钥不存在";
            throw new Exception(msg);
        }

        String r = redisString.get(RedisKeys.getPubkeyRKey());
        if (r == null) {
            String msg = "当前会话已过期, 请刷新页面后重新登入. 或者检查浏览器是否禁用了 cookie";
            throw new Exception(msg);
        }

        String plainText = RsaCryptor.decrypt(cipherText, prikey);
        return plainText.replace(r, "");
    }

    public RSAPrivateKey getPrivateKey() throws NoSuchAlgorithmException {
        String prikey = redisString.get(RedisKeys.getJwtSignKey("prikey"));
        if (prikey == null) {
            Map<String, String> rsaKeyPair = RsaCryptor.genKeyPair();
            prikey = rsaKeyPair.get("prikey");
            String pubkey = rsaKeyPair.get("pubkey");

            redisString.set(RedisKeys.getJwtSignKey("prikey"), prikey);
            redisString.set(RedisKeys.getJwtSignKey("pubkey"), pubkey);
        }

        return RsaCryptor.getRSAPrivateKey(prikey);
    }

    public RSAPublicKey getPublicKey() {
        String pubkey = redisString.get(RedisKeys.getJwtSignKey("pubkey"));
        return RsaCryptor.getRSAPublicKey(pubkey);
    }
}
