//! Utility functions for safe content rendering using the configuration-driven
//! system

use rustelo_core_lib::content::{ContentItemTrait, UnifiedContentItem};

use super::defs::{build_content_page_config, BreadcrumbData};

/// Safe breadcrumb data builder using dynamic content configuration
pub fn build_breadcrumb_data(content_type: &str, language: &str, category: &str) -> BreadcrumbData {
    let config = build_content_page_config(content_type);

    // Get routes using the dynamic routing system
    let routes = super::defs::get_content_routes(content_type, language);
    let main_url = routes.first().cloned().unwrap_or_else(|| {
        // Safe fallback using the routing system
        let fallback = rustelo_core_lib::routing::utils::get_localized_route(
            &format!("/{}", content_type),
            language,
        );
        tracing::warn!(
            "No route found for content type '{}', using fallback: {}",
            content_type,
            fallback
        );
        fallback
    });

    let main_label_key = format!("{}-page-title", content_type);

    let current_label = if config.uses_emojis {
        format!(
            "{} {}",
            rustelo_core_lib::get_category_emoji(content_type, language, category),
            category
        )
    } else {
        category.to_string()
    };

    BreadcrumbData {
        home_url: "/".to_string(),
        home_label_key: "nav-home".to_string(),
        main_url,
        main_label_key,
        current_label,
    }
}

/// Safe content getter with fallbacks
pub fn get_content_safe(
    content_map: &Option<std::collections::HashMap<String, String>>,
    key: &str,
) -> String {
    match content_map {
        Some(map) => map.get(key).cloned().unwrap_or_else(|| {
            tracing::warn!("i18n key not found: '{}'", key);
            key.to_string() // Fallback to key itself
        }),
        None => {
            tracing::warn!("No content map provided, using key as fallback: '{}'", key);
            key.to_string() // Fallback to key itself
        }
    }
}

/// Safe post filtering for categories - generic for any content type
pub fn filter_posts_by_category<'a, T>(
    posts: &'a [T],
    category: &str,
    get_category: impl Fn(&T) -> Option<&str>,
) -> Vec<&'a T> {
    posts
        .iter()
        .filter(|post| match get_category(post) {
            Some(post_cat) => post_cat.to_lowercase() == category.to_lowercase(),
            None => {
                tracing::debug!("Post has no category, excluding from category filter");
                false
            }
        })
        .collect()
}

/// Generic content category extractor for any content type that has a category
/// field
pub fn get_content_category<T>(
    item: &T,
    get_category_fn: impl Fn(&T) -> Option<&str>,
) -> Option<&str> {
    get_category_fn(item)
}

/// Content category extractor for UnifiedContentItem
pub fn get_content_item_category(post: &UnifiedContentItem) -> Option<&str> {
    post.categories().first().map(|s| s.as_str())
}

/// Safe featured content filtering - generic for any content type
pub fn get_featured_content<'a, T>(
    items: &'a [T],
    max_count: usize,
    is_featured: impl Fn(&T) -> bool,
) -> Vec<&'a T> {
    items
        .iter()
        .filter(|item| is_featured(item))
        .take(max_count)
        .collect()
}

/// Generic content featured checker for any content type that has a featured
/// field
pub fn is_content_featured_generic<T>(item: &T, get_featured_fn: impl Fn(&T) -> bool) -> bool {
    get_featured_fn(item)
}

/// Content featured checker for UnifiedContentItem
pub fn is_content_featured(post: &UnifiedContentItem) -> bool {
    post.featured()
}

/// Safe page title builder using dynamic content configuration
pub fn build_page_title(
    content_type: &str,
    category: Option<&str>,
    language: &str,
    get_content: impl Fn(&str) -> String,
) -> String {
    let config = build_content_page_config(content_type);

    match category {
        Some(cat) => {
            if config.uses_emojis {
                format!(
                    "{} {} - {}",
                    rustelo_core_lib::get_category_emoji(content_type, language, cat),
                    cat,
                    get_content(&format!("{}-category-page-title", content_type))
                )
            } else {
                format!(
                    "{} - {}",
                    cat,
                    get_content(&format!("{}-category-page-title", content_type))
                )
            }
        }
        None => get_content(&format!("{}-page-title", content_type)),
    }
}

/// Safe page description builder
pub fn build_page_description(
    content_type: &str,
    category: Option<&str>,
    get_content: impl Fn(&str) -> String,
) -> String {
    match category {
        Some(_) => get_content(&format!("{}-category-page-description", content_type)),
        None => get_content(&format!("{}-page-description", content_type)),
    }
}

/// Get content URLs dynamically using the routing system
pub fn get_content_urls(content_type: &str, language: &str) -> Vec<(String, String)> {
    let config = build_content_page_config(content_type);

    let mut urls = Vec::new();

    // Main content URL
    let main_url = rustelo_core_lib::routing::utils::get_localized_route(
        &format!("/{}", content_type),
        language,
    );
    urls.push(("main".to_string(), main_url));

    // Category URLs if enabled
    if config.uses_categories {
        let categories_url = rustelo_core_lib::routing::utils::get_localized_route(
            &format!("/{}/categories", content_type),
            language,
        );
        urls.push(("categories".to_string(), categories_url));
    }

    // Featured URLs if enabled
    if config.uses_features {
        let featured_url = rustelo_core_lib::routing::utils::get_localized_route(
            &format!("/{}/featured", content_type),
            language,
        );
        urls.push(("featured".to_string(), featured_url));
    }

    urls
}

/// Validation helpers
pub fn validate_content_type_key(key: &str) -> bool {
    !key.is_empty()
        && key
            .chars()
            .all(|c| c.is_alphanumeric() || c == '_' || c == '-')
        && super::defs::is_valid_content_type(key)
}

pub fn validate_language(lang: &str) -> bool {
    !lang.is_empty() && lang.len() <= 5 && lang.chars().all(|c| c.is_alphanumeric() || c == '-')
}

pub fn validate_category(cat: &str) -> bool {
    !cat.is_empty() && cat.len() <= 50 && !cat.contains("/")
}

/// Get available content types for validation or UI generation
pub fn get_available_content_types() -> Vec<String> {
    super::defs::get_available_content_types()
}

/// Check if features are enabled for a content type
pub fn content_type_has_features(content_type: &str) -> bool {
    let config = build_content_page_config(content_type);
    config.uses_features
}

/// Check if categories are enabled for a content type
pub fn content_type_has_categories(content_type: &str) -> bool {
    let config = build_content_page_config(content_type);
    config.uses_categories
}

/// Check if tags are enabled for a content type
pub fn content_type_has_tags(content_type: &str) -> bool {
    let config = build_content_page_config(content_type);
    config.uses_tags
}

/// Check if emojis are enabled for a content type
pub fn content_type_has_emojis(content_type: &str) -> bool {
    let config = build_content_page_config(content_type);
    config.uses_emojis
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::content::helpers::defs::{build_grid_classes, CTAViewType};

    #[test]
    fn test_build_grid_classes() {
        assert_eq!(
            build_grid_classes("grid"),
            "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6".to_string()
        );
        assert_eq!(
            build_grid_classes("row"),
            "grid grid-cols-1 gap-6".to_string()
        );
        assert_eq!(
            build_grid_classes("unknown"),
            "grid grid-cols-1 gap-6".to_string()
        );
    }

    #[test]
    fn test_cta_view_type_from_str() {
        // Test with available content types instead of hardcoded ones
        let available_types = crate::content::helpers::defs::get_available_content_types();
        if let Some(first_type) = available_types.first() {
            let first_cta_view = format!("{}CTAView", first_type);
            // Test that custom view types are properly handled
            assert_eq!(
                CTAViewType::from(first_cta_view.as_str()),
                CTAViewType::Custom(first_cta_view)
            );
        }
        // Test that non-default views become custom types
        assert_eq!(
            CTAViewType::from("UnknownView"),
            CTAViewType::Custom("UnknownView".to_string())
        );
        // Test that default view is recognized
        assert_eq!(CTAViewType::from("DefaultCTAView"), CTAViewType::Default);
    }

    #[test]
    fn test_validation_helpers() {
        assert!(validate_language("en"));
        assert!(validate_language("en-US"));
        assert!(!validate_language(""));
        assert!(!validate_language("toolongstring"));

        assert!(validate_category("rust"));
        assert!(!validate_category(""));
        assert!(!validate_category("invalid/category"));
    }
}
