import java.util.List;

public class BacaHasil {

    public static void main(String[] args) {
        HasilKueri hasil = DemoDb.query("SELECT id, nama, harga, stok FROM produk");

        System.out.println("jumlah kolom : " + hasil.getJumlahKolom());
        if (hasil.next()) {
            System.out.println("label vs indeks  : \"" + hasil.getString("nama")
                    + "\" == \"" + hasil.getString(2) + "\"");
            hasil.beforeFirst();
            System.out.println("kursor dimundurkan lewat beforeFirst()");
        }

        System.out.println();
        while (hasil.next()) {
            int id = hasil.getInt(1);
            String nama = hasil.getString("nama");
            double harga = hasil.getDouble(3);
            int stok = hasil.getInt("stok");
            String stokTampil = hasil.wasNull() ? "?" : String.valueOf(stok);
            System.out.printf("%d  %-9s Rp%.2f  stok=%s%n", id, nama, harga, stokTampil);
        }

        System.out.println();
        System.out.println("next() setelah baris terakhir -> " + hasil.next());

        System.out.println();
        System.out.println("== Jebakan umum ==");
        HasilKueri ringkas = DemoDb.query("SELECT id, nama FROM produk");
        try {
            ringkas.getInt(1); // kursor masih sebelum baris pertama
        } catch (IllegalStateException e) {
            System.out.println("baca sebelum next() : " + e.getMessage());
        }
        ringkas.next();
        try {
            ringkas.getInt(4); // hanya ada 2 kolom
        } catch (IllegalArgumentException e) {
            System.out.println("indeks di luar kolom: " + e.getMessage());
        }
    }
}

/** Meniru kontrak java.sql.ResultSet dengan data in-memory. */
class HasilKueri {

    private final List<String> kolom;
    private final List<Object[]> baris;
    private int kursor = -1;              // -1 = sebelum baris pertama
    private boolean nullTerakhir = false;

    HasilKueri(List<String> kolom, List<Object[]> baris) {
        this.kolom = List.copyOf(kolom);
        this.baris = List.copyOf(baris);
    }

    int getJumlahKolom() {
        return kolom.size();
    }

    void beforeFirst() {
        kursor = -1;
    }

    boolean next() {
        if (kursor < baris.size()) {
            kursor++;
        }
        return kursor < baris.size();
    }

    boolean wasNull() {
        return nullTerakhir;
    }

    String getString(String label) {
        return (String) nilai(indeksKolom(label));
    }

    String getString(int indeks) {
        return (String) nilai(indeksKolom(indeks));
    }

    int getInt(String label) {
        return toInt(nilai(indeksKolom(label)));
    }

    int getInt(int indeks) {
        return toInt(nilai(indeksKolom(indeks)));
    }

    double getDouble(int indeks) {
        Object v = nilai(indeksKolom(indeks));
        return v == null ? 0.0 : (Double) v;
    }

    Object getObject(int indeks) {
        return nilai(indeksKolom(indeks));
    }

    private int toInt(Object v) {
        return v == null ? 0 : (Integer) v;
    }

    private Object nilai(int idxData) {
        if (kursor < 0 || kursor >= baris.size()) {
            throw new IllegalStateException(
                    "kursor tidak berada pada baris yang valid (panggil next() lebih dulu)");
        }
        Object v = baris.get(kursor)[idxData];
        nullTerakhir = (v == null);
        return v;
    }

    private int indeksKolom(int indeks) {
        if (indeks < 1 || indeks > kolom.size()) {
            throw new IllegalArgumentException(
                    "indeks kolom tidak valid: " + indeks
                            + " (jumlah kolom: " + kolom.size() + ")");
        }
        return indeks - 1; // kontrak JDBC: indeks berbasis 1
    }

    private int indeksKolom(String label) {
        int idx = kolom.indexOf(label);
        if (idx < 0) {
            throw new IllegalArgumentException("kolom tidak ditemukan: " + label);
        }
        return idx;
    }
}

/** "Database" demo dengan dua kueri yang dikenal. */
class DemoDb {

    static HasilKueri query(String sql) {
        List<Object[]> semua = List.of(
                new Object[]{1, "Buku Java", 150_000.00, 12},
                new Object[]{2, "Mouse", 250_000.00, null},
                new Object[]{3, "Keyboard", 450_000.00, 7});
        if (sql.equals("SELECT id, nama, harga, stok FROM produk")) {
            return new HasilKueri(List.of("id", "nama", "harga", "stok"), semua);
        }
        if (sql.equals("SELECT id, nama FROM produk")) {
            return new HasilKueri(List.of("id", "nama"), semua);
        }
        throw new IllegalArgumentException("kueri tidak dikenal: " + sql);
    }
}
