package study.reactivesecurity;

import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.Date;
import java.util.List;
import com.sun.net.httpserver.HttpServer;
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.JWSHeader;
import com.nimbusds.jose.crypto.RSASSASigner;
import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.jwk.gen.RSAKeyGenerator;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;

/** 本机真实签名和JWKS网络fixture；不模拟已认证SecurityContext，不是授权服务器。 */
public final class JwtKeys implements AutoCloseable {
    private final RSAKey key;
    private final HttpServer server;
    public JwtKeys() throws Exception {
        key=new RSAKeyGenerator(2048).keyID("u31-key").generate();
        server=HttpServer.create(new InetSocketAddress("127.0.0.1",0),0);
        server.createContext("/jwks",exchange->{
            var bytes=new JWKSet(key.toPublicJWK()).toString().getBytes(StandardCharsets.UTF_8);
            exchange.getResponseHeaders().set("Content-Type","application/json");
            exchange.sendResponseHeaders(200,bytes.length);
            try(var output=exchange.getResponseBody()){output.write(bytes);}
        });
        server.start();
    }
    public String issuer() { return "http://127.0.0.1:"+server.getAddress().getPort(); }
    public String token(String variant) throws JOSEException {
        var claims=new JWTClaimsSet.Builder().issuer(variant.equals("issuer")?"https://untrusted.invalid":issuer())
            .audience(variant.equals("audience")?"other-api":"u31-api").subject("alice")
            .expirationTime(Date.from(Instant.now().plusSeconds(variant.equals("expired")?-120:120)))
            .notBeforeTime(Date.from(Instant.now().plusSeconds(variant.equals("future")?120:-10)))
            .claim("scope",variant.equals("scope")?"other":"read").claim("tenant","t1").build();
        var jwt=new SignedJWT(new JWSHeader.Builder(JWSAlgorithm.RS256).keyID("u31-key").build(),claims);
        RSAKey signer=variant.equals("signature")?new RSAKeyGenerator(2048).generate():key;
        jwt.sign(new RSASSASigner(signer));
        return jwt.serialize();
    }
    @Override public void close(){server.stop(0);System.out.println("U31OBSERVE jwks fixtureStopped=true");}
}
