//! Tests for routing utilities
//!
//! Comprehensive tests for language-agnostic routing utilities including
//! route mappings, language detection, and localized route generation.

use rustelo_core_lib::i18n::language_config::get_language_registry;
use rustelo_core_lib::routing::utils::*;

#[test]
fn debug_route_mappings() {
    let (forward_mappings, reverse_mappings) = build_route_mappings();

    println!("=== FORWARD MAPPINGS (EN -> ES) ===");
    for (en_route, es_route) in &forward_mappings {
        println!("{en_route} -> {es_route}");
    }

    println!("=== REVERSE MAPPINGS (ES -> EN) ===");
    for (es_route, en_route) in &reverse_mappings {
        println!("{es_route} -> {en_route}");
    }

    // Test specific mappings
    println!("=== LOCALIZED ROUTE TESTS ===");
    println!("/about -> es: {}", get_localized_route("/about", "es"));
    println!(
        "/services -> es: {}",
        get_localized_route("/services", "es")
    );
    println!(
        "/servicios -> en: {}",
        get_localized_route("/servicios", "en")
    );
    println!(
        "/acerca-de -> en: {}",
        get_localized_route("/acerca-de", "en")
    );

    // Check if mappings exist
    assert!(
        forward_mappings.contains_key("/about"),
        "Should have mapping for /about"
    );
    assert!(
        forward_mappings.contains_key("/services"),
        "Should have mapping for /services"
    );

    let about_spanish = forward_mappings.get("/about");
    let services_spanish = forward_mappings.get("/services");

    println!("Expected Spanish route for /about: {about_spanish:?}");
    println!("Expected Spanish route for /services: {services_spanish:?}");

    if let Some(spanish_route) = about_spanish {
        assert_eq!(
            spanish_route, "/acerca-de",
            "Should map /about to /acerca-de"
        );
    }

    if let Some(spanish_route) = services_spanish {
        assert_eq!(
            spanish_route, "/servicios",
            "Should map /services to /servicios"
        );
    }
}

#[test]
fn test_extract_lang_and_path() {
    let language_registry = get_language_registry();
    let default_language = language_registry.get_default_language();

    // Test default language routes
    let (lang, path) = extract_lang_and_path("/");
    assert_eq!(lang, default_language);
    assert_eq!(path, "/");

    let (lang, path) = extract_lang_and_path("/about");
    assert_eq!(lang, default_language);
    assert_eq!(path, "/about");

    // Test double-prefix scenarios
    let (lang, path) = extract_lang_and_path("/es/blog-es/rust-web-development-2024.html");
    assert_eq!(lang, "es");
    assert_eq!(path, "/blog-es/rust-web-development-2024.html");

    let (lang, path) = extract_lang_and_path("/recetas/kubernetes-deployment-patterns.html");
    assert_eq!(lang, "es");
    assert_eq!(path, "/recetas/kubernetes-deployment-patterns.html");

    // Test language prefix routes
    for available_lang in language_registry.get_available_languages() {
        if available_lang == default_language {
            continue;
        }

        let test_path = format!("/{available_lang}");
        let (lang, path) = extract_lang_and_path(&test_path);
        assert_eq!(lang, available_lang);
        assert_eq!(path, "/");

        let test_path = format!("/{available_lang}/about");
        let (lang, path) = extract_lang_and_path(&test_path);
        assert_eq!(lang, available_lang);
        assert_eq!(path, "/about");
    }
}

#[test]
fn test_detect_language_from_path() {
    let language_registry = get_language_registry();
    let default_language = language_registry.get_default_language();

    assert_eq!(detect_language_from_path("/about"), default_language);

    // Test all available languages
    for lang in language_registry.get_available_languages() {
        if lang == default_language {
            continue;
        }
        let test_path = format!("/{lang}/about");
        assert_eq!(detect_language_from_path(&test_path), lang);
    }
}

#[test]
fn test_is_lang_route() {
    let language_registry = get_language_registry();
    let default_language = language_registry.get_default_language();

    // Test default language routes
    assert!(is_lang_route("/about", default_language));

    // Test other language routes
    for lang in language_registry.get_available_languages() {
        if lang == default_language {
            continue;
        }
        let test_path = format!("/{lang}/about");
        assert!(is_lang_route(&test_path, &lang));
        assert!(!is_lang_route(&test_path, default_language));
    }
}

#[test]
fn test_is_lang_specific_route() {
    let language_registry = get_language_registry();
    let default_language = language_registry.get_default_language();

    // Test non-existent routes
    assert!(!is_lang_specific_route("/nonexistent", "nonexistent"));
    assert!(!is_lang_specific_route("/nonexistent", default_language));

    // Test that default language routes are not considered language-specific
    assert!(!is_lang_specific_route("/about", default_language));
}

#[test]
fn test_get_localized_route() {
    let language_registry = get_language_registry();
    let default_language = language_registry.get_default_language();
    let available_languages = language_registry.get_available_languages();

    // Test same language (should return as-is)
    assert_eq!(get_localized_route("/about", default_language), "/about");

    // Test fallback behavior for unavailable routes
    for lang in &available_languages {
        if lang == default_language {
            continue;
        }
        let fallback_path = get_localized_route("/nonexistent", lang);
        // Should either be a mapped path or fallback to prefix format
        assert!(fallback_path.starts_with('/'));
    }
}

#[test]
fn test_route_info() {
    let info = RouteInfo::from_path("/about");
    let language_registry = get_language_registry();
    assert_eq!(info.language, language_registry.get_default_language());
    assert_eq!(info.clean_path, "/about");
    assert!(info.is_default_language);
}

#[test]
fn test_is_valid_route_format() {
    assert!(is_valid_route_format("/about"));
    assert!(is_valid_route_format("/en/services"));
    assert!(!is_valid_route_format("about")); // Missing leading slash
    assert!(!is_valid_route_format("/about//page")); // Double slash
}

#[test]
fn test_dynamic_language_support() {
    let language_registry = get_language_registry();
    let available_languages = language_registry.get_available_languages();

    // Should have at least one language
    assert!(!available_languages.is_empty());

    // Should have a default language
    let default_language = language_registry.get_default_language();
    assert!(available_languages.contains(&default_language.to_string()));
}

#[test]
fn test_get_category_url() {
    // Test with dynamically discovered content types instead of hardcoded ones
    // Skip test if content directory is not accessible (e.g., in minimal test
    // environments)
    let available_types = match std::panic::catch_unwind(
        rustelo_core_lib::content_resolver::get_available_content_types,
    ) {
        Ok(types) => types,
        Err(_) => {
            println!("Skipping test - content directory not accessible");
            return;
        }
    };

    // Test the first available content type
    if let Some(first_content_type) = available_types.first() {
        let url_en = get_category_url(first_content_type, "rust", "en");
        assert_eq!(url_en, format!("/{}/rust", first_content_type));

        let url_es = get_category_url(first_content_type, "rust", "es");
        // Spanish URLs may be localized differently based on routing configuration
        assert!(url_es.contains("rust"));

        // Test category with spaces (should be converted to lowercase with dashes)
        let url_spaced = get_category_url(first_content_type, "Web Development", "en");
        assert_eq!(
            url_spaced,
            format!("/{}/web-development", first_content_type)
        );
    }

    // Test with generic content types if available
    if available_types.len() >= 2 {
        let second_content_type = &available_types[1];
        let url_en = get_category_url(second_content_type, "docker", "en");
        assert_eq!(url_en, format!("/{}/docker", second_content_type));
    }
}

#[test]
fn test_extract_lang_and_path_language_agnostic() {
    let language_registry = get_language_registry();
    let default_language = language_registry.get_default_language();

    // Test that localized paths are detected correctly without /lang/ prefix
    // Note: if localized route mappings don't exist, it falls back to default
    // language
    let (lang, path) = extract_lang_and_path("/recetas/docker");
    // Accept either Spanish detection or default language fallback
    assert!(
        lang == "es" || lang == default_language,
        "Expected 'es' or default language '{}', got '{}'",
        default_language,
        lang
    );
    assert_eq!(path, "/recetas/docker");

    let (lang, path) = extract_lang_and_path("/blog-es/rust");
    assert_eq!(lang, "es");
    assert_eq!(path, "/blog-es/rust");

    // Test that double prefix is normalized
    let (lang, path) = extract_lang_and_path("/es/recetas/docker");
    assert_eq!(lang, "es");
    assert_eq!(path, "/recetas/docker");

    let (lang, path) = extract_lang_and_path("/es/blog-es/rust");
    assert_eq!(lang, "es");
    assert_eq!(path, "/blog-es/rust");

    // Test default language paths
    let (lang, path) = extract_lang_and_path("/recipes/docker");
    assert_eq!(lang, default_language);
    assert_eq!(path, "/recipes/docker");

    let (lang, path) = extract_lang_and_path("/blog/rust");
    assert_eq!(lang, default_language);
    assert_eq!(path, "/blog/rust");
}
