import com.sun.net.httpserver.HttpServer;
import java.io.IOException;
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.time.Duration;
import java.time.LocalDate;
import java.util.Locale;

/**
 * Titik masuk inti telanjang Bagian 2: REST API CRUD berjalan di atas
 * HttpServer bawaan JDK lalu diuji in-process — server dan HttpClient
 * berbagi satu proses, server mendengarkan 127.0.0.1 pada port pilihan
 * sistem operasi (nomor port sengaja tidak dicetak agar keluaran stabil).
 * Seluruh permintaan sekuensial dari satu klien.
 */
public class AplikasiWeb {

    public static void main(String[] args) throws Exception {
        System.out.println("=== AplikasiWeb Bagian 2: REST API inti telanjang ===");
        LayananTugasWeb layanan = new LayananTugasWeb(
                new RepositoryTugasWebMemori(), LocalDate.of(2026, 1, 15));
        RouterWeb router = new RouterWeb(layanan);
        System.out.println("[Bootstrap] repository -> layanan -> router tersambung");

        HttpServer server = HttpServer.create(new InetSocketAddress("127.0.0.1", 0), 0);
        server.createContext("/", router);
        server.start();
        System.out.println("[Bootstrap] server mendengarkan di 127.0.0.1"
                + " (port dipilih sistem operasi)");
        System.out.println();

        HttpClient klien = HttpClient.newHttpClient();
        String dasar = "http://127.0.0.1:" + server.getAddress().getPort();
        try {
            kirim(klien, dasar, "POST", "/api/tugas",
                    "{\"judul\":\"Belajar arsitektur berlapis\",\"pemilik\":\"Budi\","
                            + "\"tenggat\":\"2026-02-01\"}");
            kirim(klien, dasar, "POST", "/api/tugas",
                    "{\"judul\":\"Menulis dokumentasi API\",\"pemilik\":\"Siti\","
                            + "\"tenggat\":\"2026-01-20\"}");
            kirim(klien, dasar, "GET", "/api/tugas", null);
            kirim(klien, dasar, "GET", "/api/tugas/1", null);
            kirim(klien, dasar, "PUT", "/api/tugas/1",
                    "{\"judul\":\"Belajar arsitektur berlapis (revisi)\","
                            + "\"pemilik\":\"Budi\",\"tenggat\":\"2026-02-08\"}");
            kirim(klien, dasar, "POST", "/api/tugas/1/selesai", null);
            kirim(klien, dasar, "POST", "/api/tugas/1/selesai", null);
            kirim(klien, dasar, "POST", "/api/tugas",
                    "{\"judul\":\"ab\",\"pemilik\":\"\",\"tenggat\":\"bukan-tanggal\"}");
            kirim(klien, dasar, "POST", "/api/tugas", "{\"judul\":");
            kirim(klien, dasar, "GET", "/api/tugas/99", null);
            kirim(klien, dasar, "PATCH", "/api/tugas/1", null);
            kirim(klien, dasar, "DELETE", "/api/tugas/2", null);
            kirim(klien, dasar, "GET", "/api/tugas", null);
        } finally {
            server.stop(0);
        }

        System.out.println();
        System.out.println("[Bootstrap] server berhenti; seluruh permintaan"
                + " sekuensial dari satu klien");
    }

    /** Mengirim satu permintaan lalu mencetak status, Location, dan body respons. */
    private static void kirim(HttpClient klien, String dasar, String metode,
            String path, String body) throws IOException, InterruptedException {

        HttpRequest.Builder b = HttpRequest.newBuilder()
                .uri(URI.create(dasar + path))
                .timeout(Duration.ofSeconds(5));
        if (body == null) {
            b.method(metode, HttpRequest.BodyPublishers.noBody());
        } else {
            b.header("Content-Type", "application/json")
                    .method(metode, HttpRequest.BodyPublishers.ofString(
                            body, StandardCharsets.UTF_8));
        }
        HttpResponse<String> r = klien.send(b.build(),
                HttpResponse.BodyHandlers.ofString());
        String lokasi = r.headers().firstValue("Location")
                .map(l -> " Location=" + l).orElse("");
        String isi = r.body().isEmpty() ? "(tanpa body)" : r.body();
        System.out.printf(Locale.US, "%-7s %-26s -> %d%s %s%n",
                metode, path, r.statusCode(), lokasi, isi);
    }
}
