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

public class ContohAssertLengkap {

    record Pelanggan(String id, String nama, String email, String kota) {}

    private static final Map<String, Pelanggan> BASIS_DATA = Map.of(
        "PL-001", new Pelanggan("PL-001", "Budi", "budi@example.com", "Bandung"),
        "PL-002", new Pelanggan("PL-002", "Siti", "siti@example.com", "Surabaya")
    );

    static Pelanggan cariPelanggan(String id) {
        Pelanggan p = BASIS_DATA.get(id);
        if (p == null) {
            throw new IllegalArgumentException("pelanggan tidak ditemukan: " + id);
        }
        return p;
    }

    // ---- assertion mini ala framework ----

    private static void sama(Object diharapkan, Object aktual) {
        if (!diharapkan.equals(aktual)) {
            throw new AssertionError("diharapkan '" + diharapkan
                + "' tetapi aktual '" + aktual + "'");
        }
    }

    private static void benar(boolean kondisi, String pesan) {
        if (!kondisi) {
            throw new AssertionError(pesan);
        }
    }

    // ---- assertAll mini: jalankan semua, kumpulkan kegagalan ----

    private static void grup(String nama, Runnable... pemeriksaan) {
        List<String> kegagalan = new ArrayList<>();
        for (Runnable p : pemeriksaan) {
            try {
                p.run();
            } catch (AssertionError e) {
                kegagalan.add(e.getMessage());
            }
        }
        if (kegagalan.isEmpty()) {
            System.out.println(nama + ": semua pemeriksaan lulus");
        } else {
            System.out.println(nama + ": " + kegagalan.size() + " pemeriksaan gagal");
            for (String k : kegagalan) {
                System.out.println("  - " + k);
            }
        }
    }

    public static void main(String[] args) {
        Pelanggan budi = cariPelanggan("PL-001");

        // pemeriksaan tunggal: eksekusi berhenti di kegagalan pertama
        System.out.println("-- pemeriksaan tunggal --");
        try {
            sama("Jakarta", budi.kota());
            System.out.println("kota sesuai harapan");
        } catch (AssertionError e) {
            System.out.println("terhenti di: " + e.getMessage());
        }

        // pemeriksaan berkelompok: seluruh pemeriksaan tetap dijalankan
        System.out.println("-- pemeriksaan berkelompok --");
        grup("data pelanggan PL-001",
            () -> sama("Budi", budi.nama()),
            () -> sama("Jakarta", budi.kota()),
            () -> benar(budi.email().endsWith("@example.com"),
                "email harus diakhiri @example.com"),
            () -> sama("budi@kantor.example.com", budi.email())
        );
    }
}
