//! Path manipulation utilities for routing

/// Join a base path with a sub path, handling edge cases
///
/// # Rules
/// - Empty base returns sub path as-is
/// - Empty or "/" sub path returns base path
/// - Ensures proper slash handling (no double slashes, no missing slashes)
///
/// # Examples
///
/// ```rust,ignore
/// assert_eq!(join_paths("", "/users"), "/users");
/// assert_eq!(join_paths("/api", "/users"), "/api/users");
/// assert_eq!(join_paths("/api", "users"), "/api/users");
/// assert_eq!(join_paths("/api", "/"), "/api");
/// assert_eq!(join_paths("/api", ""), "/api");
/// ```
pub fn join_paths(base: &str, sub: &str) -> String {
    if base.is_empty() {
        sub.to_string()
    } else if sub.is_empty() || sub == "/" {
        base.to_string()
    } else if sub.starts_with('/') {
        format!("{}{}", base, sub)
    } else {
        format!("{}/{}", base, sub)
    }
}

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

    #[test]
    fn test_join_paths_empty_base() {
        assert_eq!(join_paths("", "/users"), "/users");
        assert_eq!(join_paths("", "users"), "users");
    }

    #[test]
    fn test_join_paths_empty_sub() {
        assert_eq!(join_paths("/api", ""), "/api");
        assert_eq!(join_paths("/api", "/"), "/api");
    }

    #[test]
    fn test_join_paths_both_with_slash() {
        assert_eq!(join_paths("/api", "/users"), "/api/users");
    }

    #[test]
    fn test_join_paths_sub_without_slash() {
        assert_eq!(join_paths("/api", "users"), "/api/users");
    }

    #[test]
    fn test_join_paths_nested() {
        assert_eq!(join_paths("/api", "/v1/users"), "/api/v1/users");
    }

    #[test]
    fn test_join_paths_wildcard() {
        assert_eq!(join_paths("/api", "/*"), "/api/*");
    }
}
