import com.sun.net.httpserver.HttpsConfigurator;
import com.sun.net.httpserver.HttpsServer;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.security.KeyStore;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;

public class TlsLokal {
    public static void main(String[] args) throws Exception {
        // 1. Hasilkan sertifikat self-signed "dev" lewat keytool bawaan JDK
        String keytool = Path.of(System.getProperty("java.home"), "bin", "keytool").toString();
        new ProcessBuilder(keytool,
                "-genkeypair", "-alias", "server", "-keyalg", "RSA", "-keysize", "2048",
                "-validity", "1", "-dname", "CN=localhost",
                "-ext", "SAN=dns:localhost,ip:127.0.0.1",
                "-keystore", "keystore.p12", "-storetype", "PKCS12",
                "-storepass", "changeit", "-noprompt")
                .redirectOutput(ProcessBuilder.Redirect.DISCARD)
                .redirectError(ProcessBuilder.Redirect.DISCARD)
                .start().waitFor();

        // 2. Sisi server: kunci privat dan sertifikat dibaca dari keystore
        KeyStore keystore = KeyStore.getInstance(
                Path.of("keystore.p12").toFile(), "changeit".toCharArray());
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(
                KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(keystore, "changeit".toCharArray());
        SSLContext sslServer = SSLContext.getInstance("TLS");
        sslServer.init(kmf.getKeyManagers(), null, null);

        HttpsServer server = HttpsServer.create(new InetSocketAddress("localhost", 0), 0);
        server.setHttpsConfigurator(new HttpsConfigurator(sslServer));
        server.createContext("/halo", exchange -> {
            byte[] body = "halo dari tls lokal".getBytes(StandardCharsets.UTF_8);
            exchange.sendResponseHeaders(200, body.length);
            try (OutputStream os = exchange.getResponseBody()) {
                os.write(body);
            }
        });
        server.start();

        try {
            // 3. Sisi klien: sertifikat dev dipercaya lewat truststore khusus
            TrustManagerFactory tmf = TrustManagerFactory.getInstance(
                    TrustManagerFactory.getDefaultAlgorithm());
            tmf.init(keystore); // untuk dev, keystore yang sama berperan sebagai truststore
            SSLContext sslKlien = SSLContext.getInstance("TLS");
            sslKlien.init(null, tmf.getTrustManagers(), null);

            HttpClient klien = HttpClient.newBuilder()
                    .sslContext(sslKlien)
                    .build();
            HttpRequest req = HttpRequest.newBuilder()
                    .uri(URI.create("https://localhost:"
                            + server.getAddress().getPort() + "/halo"))
                    .GET()
                    .build();
            HttpResponse<String> res = klien.send(req, HttpResponse.BodyHandlers.ofString());
            System.out.println("status : " + res.statusCode());
            System.out.println("body   : " + res.body());
            System.out.println("versi  : " + res.version());
        } finally {
            server.stop(0);
        }
    }
}
