//! URL slug helpers shared by the catalog admin (products and categories).

use loco_rs::prelude::*;

/// Lowercase a string and collapse every run of non-alphanumeric characters
/// into a single dash, trimming dashes from the ends.
pub fn slugify(value: &str) -> String {
    let mut slug = String::new();
    let mut last_was_dash = false;
    for ch in value.chars().flat_map(char::to_lowercase) {
        if ch.is_ascii_alphanumeric() {
            slug.push(ch);
            last_was_dash = false;
        } else if !last_was_dash && !slug.is_empty() {
            slug.push('-');
            last_was_dash = true;
        }
    }
    slug.trim_matches('-').to_string()
}

/// Find the first slug that does not already exist, appending `-2`, `-3`, … to
/// `base` until `exists` reports the candidate as free. An empty `base` falls
/// back to `"item"`.
pub async fn unique_slug<F, Fut>(base: &str, mut exists: F) -> Result<String>
where
    F: FnMut(String) -> Fut,
    Fut: std::future::Future<Output = Result<bool>>,
{
    let base = if base.is_empty() { "item" } else { base };
    let mut slug = base.to_string();
    let mut suffix = 2;
    while exists(slug.clone()).await? {
        slug = format!("{base}-{suffix}");
        suffix += 1;
    }
    Ok(slug)
}
