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

public class AplikasiBerlapis {
    public static void main(String[] args) {
        PenyimpanProduk repository = new PenyimpanProduk();
        LayananProduk service = new LayananProduk(repository);
        MenuKonsol presentation = new MenuKonsol(service);

        presentation.tampilkanKatalog();
        presentation.pesanProduk("P-001", 2);
        presentation.pesanProduk("P-002", 1);
        presentation.pesanProduk("P-002", 5); // stok tidak cukup
        presentation.tampilkanKatalog();
    }
}

// --- Lapisan presentation: menerima permintaan dan menyajikan hasil ---
class MenuKonsol {
    private final LayananProduk layanan;

    MenuKonsol(LayananProduk layanan) {
        this.layanan = layanan;
    }

    void tampilkanKatalog() {
        System.out.println("== Katalog ==");
        layanan.daftarProduk().forEach(p -> System.out.println(
                p.kode() + " | " + p.nama() + " | Rp" + p.harga() + " | sisa " + p.stok()));
    }

    void pesanProduk(String kode, int jumlah) {
        System.out.println(layanan.pesan(kode, jumlah));
    }
}

// --- Lapisan service: aturan bisnis ---
class LayananProduk {
    private final PenyimpanProduk penyimpan;

    LayananProduk(PenyimpanProduk penyimpan) {
        this.penyimpan = penyimpan;
    }

    List<Produk> daftarProduk() {
        return penyimpan.semua();
    }

    String pesan(String kode, int jumlah) {
        Optional<Produk> hasil = penyimpan.cari(kode);
        if (hasil.isEmpty()) {
            return "Produk " + kode + " tidak ditemukan";
        }
        Produk produk = hasil.get();
        if (produk.stok() < jumlah) {
            return "Gagal memesan " + produk.nama() + ": stok hanya " + produk.stok();
        }
        penyimpan.simpan(produk.withStok(produk.stok() - jumlah));
        return "Berhasil memesan " + jumlah + " " + produk.nama();
    }
}

// --- Lapisan persistence: penyimpanan data ---
class PenyimpanProduk {
    private final Map<String, Produk> data = new LinkedHashMap<>();

    PenyimpanProduk() {
        data.put("P-001", new Produk("P-001", "Kopi Gayo 250g", 75_000, 5));
        data.put("P-002", new Produk("P-002", "Teh Melati 100g", 40_000, 3));
    }

    Optional<Produk> cari(String kode) {
        return Optional.ofNullable(data.get(kode));
    }

    List<Produk> semua() {
        return List.copyOf(data.values());
    }

    void simpan(Produk produk) {
        data.put(produk.kode(), produk);
    }
}

record Produk(String kode, String nama, long harga, int stok) {
    Produk withStok(int stokBaru) {
        return new Produk(kode, nama, harga, stokBaru);
    }
}
