pub(super) fn render_gleam_toml(
    pkg_path: &str,
    pkg_name: &str,
    dep_mode: crate::e2e::config::DependencyMode,
) -> String {
    use crate::core::template_versions::hex;
    let stdlib = hex::GLEAM_STDLIB_VERSION_RANGE;
    let gleeunit = hex::GLEEUNIT_VERSION_RANGE;
    let gleam_httpc = hex::GLEAM_HTTPC_VERSION_RANGE;
    let envoy = hex::ENVOY_VERSION_RANGE;
    let deps = match dep_mode {
        crate::e2e::config::DependencyMode::Registry => {
            format!(
                r#"{pkg_name} = ">= 0.1.0"
gleam_stdlib = "{stdlib}"
gleeunit = "{gleeunit}"
gleam_httpc = "{gleam_httpc}"
gleam_http = ">= 4.0.0 and < 5.0.0"
envoy = "{envoy}""#
            )
        }
        crate::e2e::config::DependencyMode::Local => {
            format!(
                r#"{pkg_name} = {{ path = "{pkg_path}" }}
gleam_stdlib = "{stdlib}"
gleeunit = "{gleeunit}"
gleam_httpc = "{gleam_httpc}"
gleam_http = ">= 4.0.0 and < 5.0.0"
envoy = "{envoy}""#
            )
        }
    };

    format!(
        r#"name = "e2e_gleam"
version = "0.1.0"
target = "erlang"

[dependencies]
{deps}
"#
    )
}

pub(super) fn render_e2e_helpers_source(app_name: &str) -> String {
    format!(
        "// Generated by alef. Do not edit by hand.\n\
        // E2e helper module — provides file-reading utilities for Gleam tests.\n\
        import gleam/dynamic\n\
        \n\
        /// Read a file into a BitArray via the Erlang :file module.\n\
        /// The path is relative to the e2e working directory when `gleam test` runs.\n\
        @external(erlang, \"file\", \"read_file\")\n\
        pub fn read_file_bytes(path: String) -> Result(BitArray, dynamic.Dynamic)\n\
        \n\
        /// Ensure the {app_name} OTP application and all its dependencies are started.\n\
        /// This is required when running `gleam test` outside of `mix test`, since the\n\
        /// Rustler NIF init hook needs the :{app_name} application to be started before\n\
        /// any binding-native functions can be called.\n\
        /// Calls the Erlang shim e2e_startup:start_app/0.\n\
        @external(erlang, \"e2e_startup\", \"start_app\")\n\
        pub fn start_app() -> Nil\n",
    )
}

pub(super) fn render_erlang_startup_source(app_name: &str) -> String {
    format!(
        "%% Generated by alef. Do not edit by hand.\n\
        %% Starts the {app_name} OTP application and all its dependencies.\n\
        %% Called by e2e_gleam_test.main/0 before gleeunit.main/0.\n\
        -module(e2e_startup).\n\
        -export([start_app/0]).\n\
        \n\
        start_app() ->\n\
        \x20\x20\x20\x20%% Elixir runtime must be started before {app_name} NIF init\n\
        \x20\x20\x20\x20%% because Rustler uses Elixir.Application.app_dir/2 to locate the .so.\n\
        \x20\x20\x20\x20%% Gracefully fall back when Elixir is not a runtime dependency.\n\
        \x20\x20\x20\x20case application:ensure_all_started(elixir) of\n\
        \x20\x20\x20\x20\x20\x20\x20\x20{{ok, _}} -> ok;\n\
        \x20\x20\x20\x20\x20\x20\x20\x20{{error, _}} -> ok\n\
        \x20\x20\x20\x20end,\n\
        \x20\x20\x20\x20{{ok, _}} = application:ensure_all_started({app_name}),\n\
        \x20\x20\x20\x20nil.\n",
    )
}
