import java.awt.BorderLayout;
import java.awt.Component;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;

/**
 * Menguji logika DaftarKontak, sinkronisasi KontakTableModel,
 * dan alur tombol jendela utama — semuanya tanpa membuka jendela nyata.
 */
public class DemoKontak {

    public static void main(String[] args) throws Exception {
        System.out.println("== logika inti DaftarKontak ==");
        DaftarKontak daftar = new DaftarKontak();
        daftar.tambah("Budi", "budi@example.com", "0812-1000-1001");
        daftar.tambah("Siti", "siti@example.com", "0812-1000-1002");
        daftar.tambah("Dewi", "dewi@example.com", "0813-2000-2003");
        System.out.println("jumlah = " + daftar.jumlah());
        for (Kontak k : daftar.semua()) {
            System.out.println("  " + k);
        }

        System.out.println("validasi:");
        tampilkan(() -> daftar.tambah("   ", "x@example.com", "0812"));
        tampilkan(() -> daftar.tambah("Rina", "rina.example.com", "0812"));
        tampilkan(() -> daftar.tambah("Rina", "budi@example.com", "0812"));

        System.out.println("ubah dan hapus:");
        daftar.ubah(2, "Siti Rahayu", "siti@example.com", "0815-3000-3004");
        System.out.println("  ubah id 2 -> " + daftar.cari(2).map(Kontak::nama).orElse("-"));
        daftar.hapus(1);
        System.out.println("  hapus id 1 -> jumlah = " + daftar.jumlah()
                + ", cari(1) ada = " + daftar.cari(1).isPresent());
        System.out.println("  tambah berikutnya -> " + daftar.tambah(
                "Rina", "rina@example.com", "0814-4000-4005").id()
                + " (id lama tidak dipakai ulang)");

        System.out.println("pencarian \"SIT\":");
        for (Kontak k : daftar.cari("SIT")) {
            System.out.println("  " + k.nama());
        }

        System.out.println();
        System.out.println("== sinkronisasi KontakTableModel ==");
        DaftarKontak daftarTabel = new DaftarKontak();
        KontakTableModel model = new KontakTableModel(daftarTabel);
        List<String> kejadian = new ArrayList<>();
        model.addTableModelListener((TableModelEvent e) -> {
            String jenis = switch (e.getType()) {
                case TableModelEvent.INSERT -> "INSERT";
                case TableModelEvent.DELETE -> "DELETE";
                default -> "UPDATE";
            };
            kejadian.add(jenis + " baris " + e.getFirstRow());
        });

        model.tambah("Budi", "budi@example.com", "0812-1000-1001");
        model.tambah("Siti", "siti@example.com", "0812-1000-1002");
        model.ubah(2, "Siti Rahayu", "siti@example.com", "0815-3000-3004");
        model.hapus(1);
        System.out.println("kejadian model = " + kejadian);
        System.out.println("baris tersisa  = " + model.getValueAt(0, 0)
                + " | " + model.getValueAt(0, 1));

        System.out.println();
        System.out.println("== alur tombol jendela utama ==");
        DaftarKontak daftarUi = new DaftarKontak();
        KontakTableModel modelUi = new KontakTableModel(daftarUi);
        PanelFormKontak form = new PanelFormKontak();
        PanelTabelKontak panelTabel = new PanelTabelKontak(modelUi);
        JLabel status = new JLabel("Siap.");
        JPanel tombol = JendelaUtama.bangunPanelTombol(form, modelUi, panelTabel, status);

        form.isi(new Kontak(0, "Dewi", "dewi@example.com", "0813-2000-2003"));
        tombol(tombol, "Tambah").doClick();
        System.out.println("setelah Tambah : " + status.getText());
        System.out.println("  baris tampil = " + panelTabel.tabel().getRowCount()
                + " | id terpilih = " + panelTabel.idTerpilih());
        System.out.println("  form kosong  = " + form.nama().isEmpty());

        form.isi(new Kontak(0, "Budi", "budi@example.com", "0812-1000-1001"));
        tombol(tombol, "Tambah").doClick();
        System.out.println("setelah Tambah : " + status.getText());

        tombol(tombol, "Tambah").doClick();
        System.out.println("klik dengan form kosong:");
        System.out.println("  " + status.getText());

        panelTabel.pilihBaris(0);
        tombol(tombol, "Hapus").doClick();
        System.out.println("setelah Hapus  : " + status.getText());

        isianCari(tombol).setText("bu");
        tombol(tombol, "Cari").doClick();
        System.out.println("setelah Cari   : " + status.getText());
        System.out.println("  baris tampil = " + panelTabel.tabel().getRowCount());
    }

    /** Menjalankan perintah dan mencetak exception yang terjadi. */
    private static void tampilkan(Perintah perintah) {
        try {
            perintah.jalankan();
            System.out.println("  (tanpa exception)");
        } catch (Exception e) {
            System.out.println("  " + e.getClass().getSimpleName() + ": " + e.getMessage());
        }
    }

    private static JButton tombol(JPanel panel, String teks) {
        for (Component c : panel.getComponents()) {
            if (c instanceof JButton b && teks.equals(b.getText())) {
                return b;
            }
        }
        throw new IllegalStateException("tombol tidak ada: " + teks);
    }

    private static JTextField isianCari(JPanel panel) {
        for (Component c : panel.getComponents()) {
            if (c instanceof JTextField t) {
                return t;
            }
        }
        throw new IllegalStateException("isian cari tidak ada");
    }

    /** Antarmuka satu method agar blok uji bisa melempar exception terperiksa. */
    interface Perintah {
        void jalankan() throws Exception;
    }
}
