import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Function;

/** Rantai pencarian konfigurasi: environment variable lebih dulu, default menyusul. */
public class KonfigurasiEnv {

    /** Nilai konfigurasi yang sudah terikat beserta sumbernya. */
    record Nilai(String kunci, String nilai, String sumber) {}

    /** Daftar kunci yang dibaca aplikasi beserta nilai defaultnya. */
    static final Map<String, String> DEFAULT = Map.of(
            "APP_ENV", "dev",
            "APP_DATABASE_URL", "jdbc:sqlite:data/kasir-dev.db",
            "APP_LOG_LEVEL", "DEBUG",
            "APP_POOL_SIZE", "5");

    /** Cari satu kunci: environment variable dulu, lalu default. */
    static Nilai cari(String kunci, Function<String, String> env) {
        String dariEnv = env.apply(kunci);
        if (dariEnv != null) {
            return new Nilai(kunci, dariEnv, "env");
        }
        return new Nilai(kunci, DEFAULT.get(kunci), "default");
    }

    /** Profil turunan: satu nilai APP_ENV memutuskan banyak pengaturan lain. */
    static String profil(String appEnv) {
        return switch (appEnv) {
            case "prod" -> "produksi -> pool=20, log=INFO";
            case "staging" -> "uji -> pool=10, log=INFO";
            default -> "pengembangan -> pool=5, log=DEBUG";
        };
    }

    static void skenario(String judul, Function<String, String> env) {
        System.out.println("== " + judul + " ==");
        for (String kunci : new String[]{"APP_ENV", "APP_DATABASE_URL", "APP_LOG_LEVEL"}) {
            Nilai n = cari(kunci, env);
            System.out.printf("  %-18s = %-45s (sumber: %s)%n", kunci, n.nilai(), n.sumber());
        }
        Nilai envApp = cari("APP_ENV", env);
        System.out.println("  profil            = " + profil(envApp.nilai()));
        System.out.println();
    }

    public static void main(String[] args) {
        // Skenario 1 memakai System.getenv sungguhan; di lingkungan uji ini
        // tidak ada APP_* yang diatur sehingga seluruh nilai jatuh ke default.
        skenario("Skenario 1: server tanpa environment variable", System.getenv()::get);

        // Skenario 2-3 mensimulasikan environment yang diatur operator.
        Map<String, String> envProd = new LinkedHashMap<>();
        envProd.put("APP_ENV", "prod");
        envProd.put("APP_DATABASE_URL", "jdbc:postgresql://db.internal:5432/kasir");
        skenario("Skenario 2: server produksi", envProd::get);

        Map<String, String> envCampur = new LinkedHashMap<>();
        envCampur.put("APP_DATABASE_URL", "jdbc:postgresql://db.internal:5432/kasir");
        skenario("Skenario 3: env diatur sebagian", envCampur::get);
    }
}
