import java.util.List;
import java.util.Locale;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Bagian 4: DemoPerforma — profil biaya per tahap, throughput model,
 * simulasi lebar paralelisme, dan ilustrasi batching penjadwalan.
 */
public class DemoPerforma {

    public static void main(String[] args) {
        List<String> isi = DataContoh.isiBerkas();
        HasilPipeline hasil;
        try (ExecutorService eksekutor = Executors.newVirtualThreadPerTaskExecutor()) {
            hasil = Pipeline.jalankanDenganRetry(isi, eksekutor, KebijakanRetry.baku());
        }

        List<BarisProfil> profil = ProfilPipeline.profil(hasil);
        long total = ProfilPipeline.totalBiaya(profil);
        BarisProfil macet = ProfilPipeline.kemacetan(profil);
        long sekuensial = ProfilPipeline.biayaTahapSekuensial(profil);

        System.out.println("== Profil biaya per tahap (" + isi.size()
                + " baris, model unit simulasi) ==");
        System.out.printf(Locale.US, "%-13s%6s%11s%8s%n",
                "tahap", "item", "biaya/unit", "total");
        for (BarisProfil b : profil) {
            System.out.printf(Locale.US, "%-13s%6d%11d%8d%n",
                    b.tahap().label(), b.itemDiproses(), b.biayaUnit(), b.total());
        }
        System.out.printf(Locale.US, "%-13s%6s%11s%8d%n", "total", "", "", total);
        System.out.println("kemacetan           : " + macet.tahap().label()
                + " — " + macet.total() + " unit ("
                + String.format(Locale.US, "%.1f%%", 100.0 * macet.total() / total)
                + " dari total)");
        System.out.println("unit tunggu backoff : " + hasil.unitTungguTotal()
                + " unit — waktu tunggu task, bukan beban pemroses");
        System.out.println();
        System.out.printf(Locale.US,
                "throughput sekuensial : %d baris / %d unit = %.2f baris per 100 unit%n",
                isi.size(), total, 100.0 * isi.size() / total);
        System.out.println();

        System.out.println("== Simulasi lebar paralelisme tahap mahal ==");
        System.out.printf(Locale.US, "%6s%12s%14s%9s%n",
                "lebar", "waktu-unit", "baris/100unit", "speedup");
        for (int lebar : new int[] {1, 4, 12, 36}) {
            long waktu = ProfilPipeline.waktuDinding(profil, lebar);
            System.out.printf(Locale.US, "%6d%12d%14.2f%8.2fx%n",
                    lebar, waktu, 100.0 * isi.size() / waktu, (double) total / waktu);
        }
        System.out.printf(Locale.US,
                "batas Amdahl: tahap sekuensial %d unit (%.1f%%) "
                        + "membatasi speedup maksimum %.2fx%n",
                sekuensial, 100.0 * sekuensial / total, (double) total / sekuensial);
        System.out.println();

        System.out.println("== Ilustrasi batching penjadwalan ("
                + ProfilPipeline.BIAYA_PENJADWALAN + " unit per task) ==");
        long perBaris = ProfilPipeline.biayaPenjadwalanPerBaris(isi.size());
        long perBatch = ProfilPipeline.biayaPenjadwalanPerBatch(isi.size(), 6);
        System.out.println("penjadwalan per baris : " + perBaris + " unit ("
                + isi.size() + " task)");
        System.out.println("penjadwalan per batch : " + perBatch
                + " unit (6 task berisi 6 baris)");
        System.out.printf(Locale.US, "penghematan           : %d unit (%.1f%% dari total %d)%n",
                perBaris - perBatch, 100.0 * (perBaris - perBatch) / total, total);
    }
}
