import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
import java.util.Locale;

/** Bagian 1: mencatat transaksi Januari 2026 milik Budi. */
public class DemoKeuangan {

    public static void main(String[] args) {
        // Bukti singkat kenapa nominal uang tidak boleh memakai double.
        System.out.println("double     0.1 + 0.2 = " + (0.1 + 0.2));
        System.out.println("BigDecimal 0.1 + 0.2 = "
                + new BigDecimal("0.1").add(new BigDecimal("0.2")));
        System.out.println();

        BukuKas kas = new BukuKas();
        for (Transaksi t : contohJanuari()) {
            kas.tambah(t);
        }

        System.out.println("=== Buku kas Budi — Januari 2026 ===");
        System.out.printf(Locale.US, "%-10s  %-11s  %-12s %14s  %s%n",
                "Tanggal", "Jenis", "Kategori", "Jumlah", "Keterangan");
        for (Transaksi t : kas.semua()) {
            System.out.printf(Locale.US, "%-10s  %-11s  %-12s %,14.2f  %s%n",
                    t.tanggal(), t.jenis(), t.kategori(), t.jumlah(), t.keterangan());
        }

        System.out.println();
        System.out.printf(Locale.US, "Total pemasukan  : %,14.2f%n",
                kas.total(JenisTransaksi.PEMASUKAN));
        System.out.printf(Locale.US, "Total pengeluaran: %,14.2f%n",
                kas.total(JenisTransaksi.PENGELUARAN));
        System.out.printf(Locale.US, "Saldo            : %,14.2f%n", kas.saldo());

        // Dua transaksi cacat: compact constructor Transaksi menolak keduanya.
        System.out.println();
        tolak("nominal negatif", () -> new Transaksi(LocalDate.of(2026, 1, 10),
                "Coba pengeluaran palsu", JenisTransaksi.PENGELUARAN, "Makanan",
                new BigDecimal("-100.00")));
        tolak("keterangan kosong", () -> new Transaksi(LocalDate.of(2026, 1, 11),
                "   ", JenisTransaksi.PENGELUARAN, "Makanan",
                new BigDecimal("25000.00")));
    }

    /** Menjalankan satu pembuatan Transaksi dan melaporkan pesan penolakan. */
    private static void tolak(String kasus, Runnable pembuatan) {
        try {
            pembuatan.run();
            System.out.println("DITOLAK " + kasus + ": penolakan tidak terjadi");
        } catch (IllegalArgumentException e) {
            System.out.println("DITOLAK " + kasus + ": " + e.getMessage());
        }
    }

    private static List<Transaksi> contohJanuari() {
        return List.of(
                new Transaksi(LocalDate.of(2026, 1, 5), "Gaji bulanan Januari",
                        JenisTransaksi.PEMASUKAN, "Gaji", new BigDecimal("8500000.00")),
                new Transaksi(LocalDate.of(2026, 1, 7), "Sewa tempat tinggal Januari",
                        JenisTransaksi.PENGELUARAN, "Sewa", new BigDecimal("2500000.00")),
                new Transaksi(LocalDate.of(2026, 1, 10), "Belanja bahan makanan",
                        JenisTransaksi.PENGELUARAN, "Makanan", new BigDecimal("450000.00")),
                new Transaksi(LocalDate.of(2026, 1, 18), "Makan di luar bersama Siti",
                        JenisTransaksi.PENGELUARAN, "Makanan", new BigDecimal("380000.00")),
                new Transaksi(LocalDate.of(2026, 1, 22), "Isi bensin",
                        JenisTransaksi.PENGELUARAN, "Transportasi", new BigDecimal("350000.00")),
                new Transaksi(LocalDate.of(2026, 1, 28), "Langganan streaming",
                        JenisTransaksi.PENGELUARAN, "Hiburan", new BigDecimal("250000.00")));
    }
}
