import java.util.ArrayList;
import java.util.List;

public class PanelKesehatan {

    // Status ala Spring Boot Actuator.
    enum Status {
        UP, DOWN, OUT_OF_SERVICE, UNKNOWN
    }

    // Urutan keparahan persis SimpleStatusAggregator bawaan:
    // DOWN, OUT_OF_SERVICE, UP, UNKNOWN — makin kecil makin parah.
    static int keparahan(Status s) {
        return switch (s) {
            case DOWN -> 0;
            case OUT_OF_SERVICE -> 1;
            case UP -> 2;
            case UNKNOWN -> 3;
        };
    }

    record Laporan(Status status, String detail) { }

    // Padanan HealthIndicator: satu komponen, satu keputusan.
    interface Indikator {

        String nama();

        Laporan periksa();
    }

    static class IndikatorDb implements Indikator {

        @Override
        public String nama() {
            return "db";
        }

        @Override
        public Laporan periksa() {
            // Uji nyata: kumpulan koneksi + SELECT 1.
            return new Laporan(Status.UP, "kumpulan=aktif seleksi1=ok");
        }
    }

    static class IndikatorDisk implements Indikator {

        @Override
        public String nama() {
            return "diskSpace";
        }

        @Override
        public Laporan periksa() {
            long sisaGb = 42;   // nilai tetap agar contoh deterministik
            return sisaGb >= 10
                    ? new Laporan(Status.UP, "sisa=" + sisaGb + "GB ambang=10GB")
                    : new Laporan(Status.DOWN, "sisa=" + sisaGb + "GB");
        }
    }

    static class IndikatorMail implements Indikator {

        @Override
        public String nama() {
            return "mail";
        }

        @Override
        public Laporan periksa() {
            // SMTP sedang tidak merespons.
            return new Laporan(Status.DOWN, "galat=smtp tidak merespons");
        }
    }

    // Liveness: apakah proses masih hidup? Tidak memeriksa dependensi eksternal.
    static class IndikatorPing implements Indikator {

        @Override
        public String nama() {
            return "ping";
        }

        @Override
        public Laporan periksa() {
            return new Laporan(Status.UP, "proses=hidup");
        }
    }

    // Padanan health group: sekumpulan indikator dengan nama.
    record Grup(String nama, List<Indikator> anggota) {

        Status status() {
            Status parah = Status.UP;
            for (Indikator i : anggota) {
                Laporan l = i.periksa();
                if (keparahan(l.status()) < keparahan(parah)) {
                    parah = l.status();
                }
            }
            return parah;
        }
    }

    public static void main(String[] args) {
        List<Indikator> semua = List.of(
                new IndikatorDb(),
                new IndikatorDisk(),
                new IndikatorMail());

        System.out.println("== Indikator kesehatan ==");
        for (Indikator i : semua) {
            Laporan l = i.periksa();
            System.out.printf("%-10s %-6s %s%n", i.nama(), l.status(), l.detail());
        }

        // Agregasi worst-of: satu komponen DOWN menjatuhkan seluruh status.
        Status keseluruhan = new Grup("keseluruhan", semua).status();
        System.out.println();
        System.out.println("== Agregasi (worst-of: DOWN > OUT_OF_SERVICE > UP > UNKNOWN) ==");
        System.out.println("status /actuator/health: " + keseluruhan);

        Grup liveness = new Grup("livenessProbe", List.of(new IndikatorPing()));
        Grup readiness = new Grup("readinessProbe",
                List.of(new IndikatorDb(), new IndikatorMail()));

        System.out.println();
        System.out.println("== Health groups (probe orkestrator) ==");
        System.out.printf("%-15s %-6s indikator: ping        -> pod TIDAK direstart%n",
                liveness.nama(), liveness.status());
        System.out.printf("%-15s %-6s indikator: db, mail    -> trafik dihentikan, pod tetap hidup%n",
                readiness.nama(), readiness.status());

        System.out.println();
        System.out.println("== Keputusan orkestrator ==");
        System.out.println("liveness  UP  : jangan restart, proses sehat");
        System.out.println("readiness DOWN: jangan kirim trafik baru ke instance ini");
    }
}
