import java.util.List;
import java.util.Set;
import java.util.TreeSet;

/** Membandingkan dua cara memotong sistem yang sama menjadi service. */
public class BatasKapabilitas {
    /** Satu service beserta daftar tanggung jawab yang ditampungnya. */
    record Layanan(String nama, List<String> isi) {}

    // Alur "lihat produk": tiga kebutuhan pada domain katalog
    static final List<String> ALUR_LIHAT_PRODUK =
            List.of("ui katalog", "logika katalog", "data katalog");

    // Fitur baru "voucher": tiga kebutuhan pada domain pesanan
    static final List<String> FITUR_VOUCHER =
            List.of("ui pesanan", "logika pesanan", "data pesanan");

    public static void main(String[] args) {
        // Potongan A: batas mengikuti lapisan teknis (ui / logika / data)
        List<Layanan> perLapisan = List.of(
                new Layanan("svc-ui", List.of(
                        "ui katalog", "ui pesanan", "ui pengiriman")),
                new Layanan("svc-logika", List.of(
                        "logika katalog", "logika pesanan", "logika pengiriman")),
                new Layanan("svc-data", List.of(
                        "data katalog", "data pesanan", "data pengiriman")));

        // Potongan B: batas mengikuti kapabilitas bisnis (katalog / pesanan / pengiriman)
        List<Layanan> perKapabilitas = List.of(
                new Layanan("svc-katalog", List.of(
                        "ui katalog", "logika katalog", "data katalog")),
                new Layanan("svc-pesanan", List.of(
                        "ui pesanan", "logika pesanan", "data pesanan")),
                new Layanan("svc-pengiriman", List.of(
                        "ui pengiriman", "logika pengiriman", "data pengiriman")));

        System.out.println("== POTONGAN PER LAPISAN TEKNIS ==");
        tampilkan(perLapisan);
        laporan(perLapisan);

        System.out.println();
        System.out.println("== POTONGAN PER KAPABILITAS BISNIS ==");
        tampilkan(perKapabilitas);
        laporan(perKapabilitas);
    }

    static void tampilkan(List<Layanan> daftar) {
        for (Layanan l : daftar) {
            System.out.println("  " + String.format("%-16s", l.nama()) + ": "
                    + String.join(", ", l.isi()));
        }
    }

    static void laporan(List<Layanan> daftar) {
        Set<String> voucher = penampung(daftar, FITUR_VOUCHER);
        Set<String> lihatProduk = penampung(daftar, ALUR_LIHAT_PRODUK);
        System.out.println("  fitur \"voucher\" dikerjakan oleh "
                + voucher.size() + " service: " + voucher);
        System.out.println("  alur \"lihat produk\" melewati "
                + lihatProduk.size() + " service: " + lihatProduk);
    }

    /** Kumpulan service yang menampung minimal satu kebutuhan pada daftar. */
    static Set<String> penampung(List<Layanan> daftar, List<String> kebutuhan) {
        Set<String> hasil = new TreeSet<>();
        for (Layanan l : daftar) {
            for (String k : kebutuhan) {
                if (l.isi().contains(k)) {
                    hasil.add(l.nama());
                }
            }
        }
        return hasil;
    }
}
