//! Small URL-assembly helpers shared by every HTTP caller in the
//! workspace.
//!
//! All clients (desktop, server-internal, server-to-Ollama/Whisper)
//! end up building `{base_url}{path}` where `base_url` comes from
//! config and may or may not carry a trailing slash. The raw
//! `format!("{}{}", base.trim_end_matches('/'), path)` pattern was
//! duplicated in seven call sites; centralizing it here keeps any
//! future rule (enforce a leading slash on the path, tolerate
//! `http://host/` with a path segment, normalize percent-encoding)
//! in one place.

/// Join a base URL with an absolute path, normalizing any trailing
/// slash on the base. The path is expected to start with `/`; no
/// validation is performed — callers already pass constants like
/// [`crate::UPLOAD_PATH`].
///
/// Examples:
/// - `join_url("http://h", "/a")` → `"http://h/a"`
/// - `join_url("http://h/", "/a")` → `"http://h/a"`
/// - `join_url("http://h//", "/a")` → `"http://h/a"`
pub fn join_url(base: &str, path: &str) -> String {
    let mut out = String::with_capacity(base.len() + path.len());
    out.push_str(base.trim_end_matches('/'));
    out.push_str(path);
    out
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn no_trailing_slash_on_base() {
        assert_eq!(join_url("http://h", "/a"), "http://h/a");
    }

    #[test]
    fn single_trailing_slash_on_base() {
        assert_eq!(join_url("http://h/", "/a"), "http://h/a");
    }

    #[test]
    fn multiple_trailing_slashes_on_base() {
        assert_eq!(join_url("http://h///", "/a"), "http://h/a");
    }

    #[test]
    fn nested_path() {
        assert_eq!(
            join_url("https://example.com/", "/api/upload"),
            "https://example.com/api/upload"
        );
    }
}
