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

public class AturanDependensi {
    public static void main(String[] args) {
        PenyimpanKarcisMemori penyimpan = new PenyimpanKarcisMemori();
        LayananParkir useCase = new LayananParkir(penyimpan);
        PengelolaParkiran controller = new PengelolaParkiran(useCase);

        controller.kendaraanMasuk("B 1234 CD", 8);
        controller.kendaraanMasuk("B 5678 EF", 14);
        controller.kendaraanKeluar("B 1234 CD", 11);
        controller.kendaraanKeluar("B 5678 EF", 15);
        controller.kendaraanKeluar("B 9999 ZZ", 16); // plat tidak terdaftar
    }
}

// ===== Lingkar dalam: Entities =====
record Karcis(String plat, int jamMasuk) {
}

// ===== Lingkar kedua: Use cases (port milik use case) =====
interface PenyimpanKarcis {
    void simpan(Karcis karcis);

    Optional<Karcis> cari(String plat);

    void hapus(String plat);
}

class LayananParkir {
    private final PenyimpanKarcis penyimpan;

    LayananParkir(PenyimpanKarcis penyimpan) {
        this.penyimpan = penyimpan;
    }

    String masuk(String plat, int jamMasuk) {
        if (penyimpan.cari(plat).isPresent()) {
            return "Ditolak: " + plat + " sudah berada di dalam";
        }
        penyimpan.simpan(new Karcis(plat, jamMasuk));
        return "Masuk: " + plat + " pukul " + jamMasuk + ".00";
    }

    String keluar(String plat, int jamKeluar) {
        Optional<Karcis> hasil = penyimpan.cari(plat);
        if (hasil.isEmpty()) {
            return "Keluar gagal: " + plat + " tidak terdaftar";
        }
        Karcis karcis = hasil.get();
        int durasi = Math.max(jamKeluar - karcis.jamMasuk(), 1);
        long biaya = durasi * 3_000L;
        penyimpan.hapus(plat);
        return "Keluar: " + plat + ", " + durasi + " jam, Rp" + biaya;
    }
}

// ===== Lingkar ketiga: Interface adapters =====
class PengelolaParkiran {
    private final LayananParkir useCase;

    PengelolaParkiran(LayananParkir useCase) {
        this.useCase = useCase;
    }

    void kendaraanMasuk(String plat, int jam) {
        System.out.println(useCase.masuk(plat, jam));
    }

    void kendaraanKeluar(String plat, int jam) {
        System.out.println(useCase.keluar(plat, jam));
    }
}

class PenyimpanKarcisMemori implements PenyimpanKarcis {
    private final Map<String, Karcis> aktif = new LinkedHashMap<>();

    public void simpan(Karcis karcis) {
        aktif.put(karcis.plat(), karcis);
    }

    public Optional<Karcis> cari(String plat) {
        return Optional.ofNullable(aktif.get(plat));
    }

    public void hapus(String plat) {
        aktif.remove(plat);
    }
}
