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

public class TabelRelasi {

    record Pelanggan(int id, String nama, String kota) {}
    record Pesanan(int id, int pelangganId, String barang, long total) {}
    record Tag(int id, String label) {}
    record PelangganTag(int pelangganId, int tagId) {}

    public static void main(String[] args) {
        List<Pelanggan> pelanggan = new ArrayList<>(List.of(
                new Pelanggan(1, "Budi", "Jakarta"),
                new Pelanggan(2, "Siti", "Bandung"),
                new Pelanggan(3, "Dewi", "Surabaya")));

        List<Pesanan> pesanan = new ArrayList<>(List.of(
                new Pesanan(101, 1, "Buku Java", 150_000),
                new Pesanan(102, 2, "Mouse", 250_000),
                new Pesanan(103, 2, "Keyboard", 450_000)));

        System.out.println("== Tabel pelanggan ==");
        cetakPelanggan(pelanggan);

        // Uji 1: primary key duplikat (id 2 sudah dipakai Siti)
        try {
            tambahPelanggan(pelanggan, new Pelanggan(2, "Ranto", "Medan"));
        } catch (IllegalStateException e) {
            System.out.println("DITOLAK: " + e.getMessage());
        }

        // Uji 2: foreign key tidak valid (pelangganId 99 tidak ada)
        try {
            tambahPesanan(pelanggan, pesanan, new Pesanan(104, 99, "Monitor", 1_200_000));
        } catch (IllegalStateException e) {
            System.out.println("DITOLAK: " + e.getMessage());
        }

        // Uji 3: baris yang sah lolos pemeriksaan kunci
        tambahPesanan(pelanggan, pesanan, new Pesanan(104, 3, "Monitor", 1_200_000));
        System.out.println("Pesanan 104 tersimpan untuk pelanggan 3 (Dewi).");

        // Relasi 1-N: gabungkan pesanan dengan pelanggan pemiliknya
        System.out.println();
        System.out.println("== Laporan pesanan (gabungan pelanggan <-> pesanan) ==");
        for (Pesanan p : pesanan) {
            Pelanggan c = cariPelanggan(pelanggan, p.pelangganId());
            System.out.printf("%-4d %-6s %-9s %-8s Rp%d%n",
                    p.id(), c.nama(), p.barang(), c.kota(), p.total());
        }

        // Relasi N-M: satu pelanggan boleh punya banyak tag, satu tag dipakai
        // banyak pelanggan, lewat tabel junction pelanggan_tag
        List<Tag> tag = List.of(new Tag(1, "vip"), new Tag(2, "prioritas"));
        List<PelangganTag> pelangganTag = List.of(
                new PelangganTag(1, 1),
                new PelangganTag(1, 2),
                new PelangganTag(2, 2),
                new PelangganTag(3, 1));
        System.out.println();
        System.out.println("== Tag pelanggan (relasi N-M lewat tabel junction) ==");
        for (Pelanggan c : pelanggan) {
            List<String> label = new ArrayList<>();
            for (PelangganTag pt : pelangganTag) {
                if (pt.pelangganId() == c.id()) {
                    label.add(cariTag(tag, pt.tagId()).label());
                }
            }
            System.out.printf("%-6s -> %s%n", c.nama(), label);
        }
    }

    static void tambahPelanggan(List<Pelanggan> tabel, Pelanggan baru) {
        for (Pelanggan c : tabel) {
            if (c.id() == baru.id()) {
                throw new IllegalStateException(
                        "primary key pelanggan.id duplikat: " + baru.id());
            }
        }
        tabel.add(baru);
    }

    static void tambahPesanan(List<Pelanggan> pelanggan, List<Pesanan> tabel, Pesanan baru) {
        if (cariPelanggan(pelanggan, baru.pelangganId()) == null) {
            throw new IllegalStateException(
                    "foreign key pesanan.pelangganId tidak ditemukan: " + baru.pelangganId());
        }
        tabel.add(baru);
    }

    static Pelanggan cariPelanggan(List<Pelanggan> tabel, int id) {
        for (Pelanggan c : tabel) {
            if (c.id() == id) {
                return c;
            }
        }
        return null;
    }

    static Tag cariTag(List<Tag> tabel, int id) {
        for (Tag t : tabel) {
            if (t.id() == id) {
                return t;
            }
        }
        return null;
    }

    static void cetakPelanggan(List<Pelanggan> tabel) {
        System.out.println("| id | nama   | kota      |");
        System.out.println("|----|--------|-----------|");
        for (Pelanggan c : tabel) {
            System.out.printf("| %-2d | %-6s | %-9s |%n", c.id(), c.nama(), c.kota());
        }
    }
}
