//! Language detection and path extraction utilities
//!
//! This module handles dynamic language detection from URL paths,
//! supporting any number of languages based on configuration.

use rustelo_language::get_language_registry;

use super::components::RouteConfigToml;
use super::config::{build_route_mappings, load_routes_config};
// RouteMetadataAccess is only used by tools crate during build time

/// Extract language and clean path from a URL path (dynamic language detection)
pub fn extract_lang_and_path(path: &str) -> (String, String) {
    let language_registry = get_language_registry();
    let available_languages = language_registry.get_available_languages();
    let default_language = language_registry.get_default_language();

    // Handle empty or root path
    if path.is_empty() || path == "/" {
        return (default_language.to_string(), "/".to_string());
    }

    // Check if path starts with any language prefix
    for lang in &available_languages {
        if lang == default_language {
            continue; // Skip default language prefix check
        }

        let prefix = format!("/{lang}");
        if let Some(rest) = path.strip_prefix(&prefix) {
            if rest.is_empty() || rest == "/" {
                return (lang.clone(), "/".to_string());
            } else if rest.starts_with('/') {
                // Check for double-prefix scenarios and normalize them
                // e.g., "/es/blog-es/..." should be "/blog-es/..."
                // Use configuration to detect language-specific paths
                let config = load_routes_config();
                for route in &config.routes {
                    if route.get_enabled()
                        && route.get_language() == Some(lang.clone())
                        && rest.starts_with(route.path.split('{').next().unwrap_or(""))
                    {
                        // Found a localized route that shouldn't have the /lang/ prefix
                        return (lang.clone(), rest.to_string());
                    }
                }
                return (lang.clone(), rest.to_string());
            }
        }
    }

    // Check route configuration for both exact matches and language-specific
    // patterns
    let config = load_routes_config();

    // First check for language-specific content paths (before exact route matches)
    for route in &config.routes {
        if !route.get_enabled() {
            continue;
        }

        // Check if the path starts with a language-specific route pattern
        let route_prefix = route.path.split('{').next().unwrap_or(&route.path);
        if path.starts_with(route_prefix)
            && route.get_language() != Some(default_language.to_string())
        {
            return (route.get_language().unwrap_or_default(), path.to_string());
        }
    }

    // Check if this exact path exists in route configuration (language-agnostic)
    for route in &config.routes {
        if route.get_enabled() && route.path == path {
            // For default language routes, return clean path; for others, use reverse
            // mapping
            if route.get_language() == Some(default_language.to_string()) {
                return (route.get_language().unwrap_or_default(), path.to_string());
            } else {
                // Use reverse mapping to get the canonical/clean path
                let (_, reverse_mappings) = build_route_mappings();
                let clean_path = reverse_mappings
                    .get(path)
                    .cloned()
                    .unwrap_or_else(|| path.to_string());
                return (route.get_language().unwrap_or_default(), clean_path);
            }
        }
    }

    // For certain URL patterns that should always default to the default language,
    // ignore localStorage preferences to avoid confusion
    #[cfg_attr(not(target_arch = "wasm32"), allow(unused_variables))]
    let should_default_to_base_lang = {
        // Check if this path belongs to default language routes
        let config = load_routes_config();
        let default_language = get_language_registry().get_default_language();
        config.routes.iter().any(|route| {
            route.get_enabled()
                && route.get_language() == Some(default_language.to_string())
                && (route.path == path
                    || path.starts_with(&route.path.replace("{", "").replace("}", "")))
        })
    };

    // For unknown routes, check for stored language preference in cookies to
    // maintain context (language-agnostic) but only if the path doesn't
    // explicitly indicate it should use default language
    #[cfg(target_arch = "wasm32")]
    {
        if !should_default_to_base_lang {
            // Check cookie for language preference (matching i18n.rs implementation)
            match js_sys::eval("document.cookie") {
                Ok(cookie_value) => {
                    if let Some(cookie_string) = cookie_value.as_string() {
                        for cookie in cookie_string.split(';') {
                            let cookie = cookie.trim();
                            if let Some(value) = cookie.strip_prefix("preferred_language=") {
                                let available_languages =
                                    language_registry.get_available_languages();
                                if available_languages.contains(&value.to_string())
                                    && value != default_language
                                {
                                    return (value.to_string(), path.to_string());
                                }
                            }
                        }
                    }
                }
                Err(_) => {}
            }
        }
    }

    // Default to default language
    (default_language.to_string(), path.to_string())
}

/// Detect language from URL path
pub fn detect_language_from_path(path: &str) -> String {
    extract_lang_and_path(path).0
}

/// Check if a route is for a specific language
pub fn is_lang_route(path: &str, target_lang: &str) -> bool {
    let (detected_lang, _) = extract_lang_and_path(path);
    detected_lang == target_lang
}

/// Generate language-aware category URL using route configuration
/// Returns the correct localized path based on language and category parameter
pub fn get_category_url(base_path: &str, category: &str, language: &str) -> String {
    let config = load_routes_config();
    let category_normalized = category.replace(" ", "-").to_lowercase();

    // Find parametric route with {category} placeholder for this language
    let parametric_route = config.routes.iter().find(|route| {
        route.get_enabled()
            && route.get_language() == Some(language.to_string())
            && route.path.contains("{category}")
            && route.path.starts_with(base_path)
    });

    if let Some(route) = parametric_route {
        // Replace the {category} parameter with the actual category
        let result = route.path.replace("{category}", &category_normalized);
        tracing::debug!(
            "Found parametric route for {}/{}: {} -> {}",
            base_path,
            language,
            route.path,
            result
        );
        result
    } else {
        // Fallback: find base route that matches the base_path and append category
        let base_route = config.routes.iter().find(|route| {
            route.get_enabled()
                && route.get_language() == Some(language.to_string())
                && route.path == base_path
        });

        if let Some(base) = base_route {
            // Use the base route path and append category
            let result = format!("{}/{}", base.path, category_normalized);
            tracing::debug!(
                "Using base route fallback for {}/{}: {} -> {}",
                base_path,
                language,
                base.path,
                result
            );
            result
        } else {
            // Final fallback: construct URL using the provided base_path
            let result = format!("{}/{}", base_path, category_normalized);
            tracing::warn!(
                "No route configuration found for {} in language {}, using generic path: {}",
                base_path,
                language,
                result
            );
            result
        }
    }
}

/// Generate language-aware tag URL
/// Alias for get_category_url since tags and categories use the same URL
/// structure
pub fn get_tag_url(base_path: &str, tag: &str, language: &str) -> String {
    get_category_url(base_path, tag, language)
}

/// Get the base path for a component in a specific language from route
/// configuration
pub fn get_component_base_path(component: &str, language: &str) -> Option<String> {
    let config = load_routes_config();

    #[cfg(not(target_arch = "wasm32"))]
    tracing::debug!(
        "🔍 get_component_base_path: Looking for component='{}', language='{}'",
        component,
        language
    );

    let result = config
        .routes
        .iter()
        .find(|route| {
            let matches = route.get_enabled()
                && route.get_language() == Some(language.to_string())
                && route.component == component
                && !route.path.contains("{"); // Find non-parametric routes

            #[cfg(not(target_arch = "wasm32"))]
            if matches {
                tracing::debug!(
                    "✅ get_component_base_path: Found route: path='{}', component='{}', \
                     language='{}'",
                    route.path,
                    route.component,
                    language
                );
            }
            matches
        })
        .map(|route| route.path.clone());

    #[cfg(not(target_arch = "wasm32"))]
    if let Some(ref path) = result {
        tracing::debug!(
            "✅ get_component_base_path: Returning path='{}' for component='{}', language='{}'",
            path,
            component,
            language
        );
    } else {
        tracing::warn!(
            "❌ get_component_base_path: No route found for component='{}', language='{}'",
            component,
            language
        );
    }

    result
}

/// Get canonical URL for a given path and language using route configuration
pub fn get_canonical_url(path: &str, language: &str, base_url: &str) -> String {
    let config = load_routes_config();
    let (_, clean_path) = extract_lang_and_path(path);

    // Find the route in route configuration for this language
    if let Some(route) = config.routes.iter().find(|r| {
        r.get_enabled()
            && r.get_language() == Some(language.to_string())
            && (r.path == path || r.get_canonical_path().is_some_and(|cp| cp == clean_path))
    }) {
        if route.path == "/" {
            base_url.to_string()
        } else {
            format!("{base_url}{}", route.path)
        }
    } else {
        // Fallback: use the path as-is
        if path == "/" {
            base_url.to_string()
        } else {
            format!("{base_url}{path}")
        }
    }
}

/// Get the base path for a content type in a specific language
/// This directly looks up the route definition for a content type in the target
/// language
pub fn get_content_type_base_path(content_type: &str, target_language: &str) -> Option<String> {
    let config = load_routes_config();

    #[cfg(target_arch = "wasm32")]
    web_sys::console::log_1(
        &format!(
            "🔍 get_content_type_base_path: Looking for content_type='{}' in language='{}'",
            content_type, target_language
        )
        .into(),
    );

    // Find the route for the target language and content type
    let result = config
        .routes
        .iter()
        .find(|r| {
            r.get_enabled()
                && r.get_language() == Some(target_language.to_string())
                && r.content_type.as_deref() == Some(content_type)
        })
        .map(|route| {
            #[cfg(target_arch = "wasm32")]
            web_sys::console::log_1(
                &format!(
                    "✅ get_content_type_base_path: Found route path='{}' for content_type='{}' \
                     in language='{}'",
                    route.path, content_type, target_language
                )
                .into(),
            );
            route.path.clone()
        });

    if result.is_none() {
        #[cfg(target_arch = "wasm32")]
        web_sys::console::log_1(
            &format!(
                "⚠️ get_content_type_base_path: No route found for content_type='{}' in \
                 language='{}'",
                content_type, target_language
            )
            .into(),
        );
    }

    result
}

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

    #[test]
    fn test_extract_lang_and_path_default() {
        let (_lang, path) = extract_lang_and_path("/");
        assert_eq!(path, "/");
        // Language should be default language from registry
    }

    #[test]
    fn test_detect_language_from_path() {
        let lang = detect_language_from_path("/");
        assert!(!lang.is_empty());
    }

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

        assert!(is_lang_route("/", default_language));
    }

    #[test]
    fn test_get_canonical_url() {
        let url = get_canonical_url("/", "en", "https://example.com");
        assert!(url.starts_with("https://example.com"));
    }
}
