import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

// Layanan katalog dan keanggotaan: satu objek memegang seluruh data perpustakaan.
public class Perpustakaan {

    // LinkedHashMap: pencarian cepat berdasar kunci DAN urutan sisip terjaga,
    // sehingga daftar buku/anggota selalu tampil sesuai urutan pendaftaran.
    private final Map<String, Buku> katalog = new LinkedHashMap<>();
    private final Map<String, Anggota> anggota = new LinkedHashMap<>();

    public void tambahBuku(Buku buku) {
        Buku sebelumnya = katalog.putIfAbsent(buku.isbn(), buku);
        if (sebelumnya != null) {
            throw new PerpustakaanException(
                    "ISBN sudah terdaftar: " + buku.isbn());
        }
    }

    public void daftarkan(Anggota baru) {
        Anggota sebelumnya = anggota.putIfAbsent(baru.id(), baru);
        if (sebelumnya != null) {
            throw new PerpustakaanException(
                    "ID anggota sudah terdaftar: " + baru.id());
        }
    }

    public Buku cariBukuIsbn(String isbn) {
        Buku buku = katalog.get(isbn);
        if (buku == null) {
            throw new BukuTidakDitemukanException(
                    "ISBN tidak ada di katalog: " + isbn);
        }
        return buku;
    }

    public Anggota cariAnggota(String id) {
        Anggota dicari = anggota.get(id);
        if (dicari == null) {
            throw new AnggotaTidakDitemukanException(
                    "ID anggota tidak terdaftar: " + id);
        }
        return dicari;
    }

    /** Cari buku yang judul, penulis, atau ISBN-nya memuat kata kunci. */
    public List<Buku> cariBuku(String kataKunci) {
        List<Buku> hasil = new ArrayList<>();
        for (Buku buku : katalog.values()) {
            if (buku.cocokKataKunci(kataKunci)) {
                hasil.add(buku);
            }
        }
        return hasil;
    }

    /** Salinan katalog dalam urutan pendaftaran. */
    public List<Buku> semuaBuku() {
        return List.copyOf(katalog.values());
    }

    /** Salinan daftar anggota dalam urutan pendaftaran. */
    public List<Anggota> semuaAnggota() {
        return List.copyOf(anggota.values());
    }

    public int jumlahBuku() {
        return katalog.size();
    }

    public int jumlahAnggota() {
        return anggota.size();
    }
}
