//! Standalone URL localization utilities
//!
//! This module provides language-aware URL routing that works across
//! both SSR and client contexts, supporting any languages discovered from filesystem.
//! Now fully language-agnostic using dynamic language discovery.

use std::collections::HashMap;

/// Language-specific URL mappings for special routes
pub struct LanguageRoutes {
    /// Maps English paths to localized equivalents
    routes: HashMap<&'static str, HashMap<&'static str, &'static str>>,
}

impl Default for LanguageRoutes {
    fn default() -> Self {
        let mut routes = HashMap::new();

        // Spanish route mappings
        let mut es_routes = HashMap::new();
        es_routes.insert("/services", "/servicios");
        es_routes.insert("/contact", "/contactar");
        es_routes.insert("/work-request", "/solicitud-trabajo");
        es_routes.insert("/about", "/sobre-mi");
        // Content type routes are handled dynamically by routing system
        es_routes.insert("/privacy", "/privacidad");
        es_routes.insert("/legal", "/legal");

        routes.insert("es", es_routes);

        Self { routes }
    }
}

impl LanguageRoutes {
    /// Get localized path for a specific language - now fully language-agnostic
    pub fn get_localized_path(&self, path: &str, target_lang: &str) -> String {
        let default_lang = crate::i18n::discovery::get_default_language();

        // If target language is the default, convert to default language format
        if target_lang == default_lang {
            self.to_default_language(path)
        } else {
            // For non-default languages, add language prefix and handle mappings
            self.to_non_default_language(path, target_lang)
        }
    }

    /// Convert any path to default language (remove language prefix and map back)
    fn to_default_language(&self, path: &str) -> String {
        let discovered_languages = crate::i18n::discovery::discover_available_languages();
        let default_lang = crate::i18n::discovery::get_default_language();

        // Check if path starts with any non-default language prefix
        for lang in discovered_languages {
            if lang != default_lang {
                let prefix = format!("/{}", lang);
                if path.starts_with(&prefix) {
                    let clean_path = path.strip_prefix(&prefix).unwrap_or(path);
                    if clean_path.is_empty() {
                        return "/".to_string();
                    }

                    // Reverse lookup: find default language equivalent
                    if let Some(lang_routes) = self.routes.get(lang.as_str()) {
                        for (default_path, lang_path) in lang_routes.iter() {
                            if clean_path == *lang_path {
                                return default_path.to_string();
                            }
                        }
                    }

                    return clean_path.to_string();
                }
            }
        }

        // Path is already in default language format
        path.to_string()
    }

    /// Convert any path to non-default language (add prefix or map to target equivalent)
    fn to_non_default_language(&self, path: &str, target_lang: &str) -> String {
        let target_prefix = format!("/{}", target_lang);

        // If already in target language, return as-is
        if path.starts_with(&target_prefix) {
            return path.to_string();
        }

        // Handle root path - should become /lang for non-default languages
        if path == "/" {
            return target_prefix;
        }

        // Check for special route mappings for this language
        if let Some(lang_routes) = self.routes.get(target_lang) {
            if let Some(target_path) = lang_routes.get(path) {
                return format!("{}{}", target_prefix, target_path);
            }
        }

        // Default: add language prefix
        format!("{}{}", target_prefix, path)
    }
}

/// Main URL localization utility
pub struct UrlLocalizer {
    routes: LanguageRoutes,
}

impl Default for UrlLocalizer {
    fn default() -> Self {
        Self::new()
    }
}

impl UrlLocalizer {
    /// Create a new URL localizer with default route mappings
    pub fn new() -> Self {
        Self {
            routes: LanguageRoutes::default(),
        }
    }

    /// Create a localized URL for the given path and target language
    pub fn localize_url(&self, path: &str, target_lang: &str) -> String {
        if !crate::i18n::discovery::is_supported_language(target_lang) {
            return path.to_string();
        }

        self.routes.get_localized_path(path, target_lang)
    }

    /// Extract language code from a URL path - now supports any discovered language
    pub fn extract_language(&self, path: &str) -> &str {
        let discovered_languages = crate::i18n::discovery::discover_available_languages();

        // Check if path starts with any discovered language prefix
        for lang in discovered_languages {
            let prefix = format!("/{}", lang);
            if path.starts_with(&prefix) {
                return Box::leak(lang.clone().into_boxed_str());
            }
        }

        // Default to primary discovered language
        crate::i18n::discovery::get_default_language()
    }

    /// Get the clean path without language prefix - now supports any discovered language
    pub fn clean_path(&self, path: &str) -> String {
        let discovered_languages = crate::i18n::discovery::discover_available_languages();

        // Check if path starts with any discovered language prefix
        for lang in discovered_languages {
            let prefix = format!("/{}", lang);
            let prefix_with_slash = format!("{}/", prefix);

            if path.starts_with(&prefix_with_slash) {
                return path.strip_prefix(&prefix).unwrap_or("/").to_string();
            } else if path == prefix {
                return "/".to_string();
            }
        }

        path.to_string()
    }

    /// Check if a language is supported
    pub fn is_supported_language(&self, lang: &str) -> bool {
        crate::i18n::discovery::is_supported_language(lang)
    }

    /// Get all supported languages
    pub fn supported_languages(&self) -> &Vec<String> {
        crate::i18n::discovery::discover_available_languages()
    }

    /// Get default language
    pub fn default_language(&self) -> &'static str {
        crate::i18n::discovery::get_default_language()
    }
}

/// Global URL localizer instance
static URL_LOCALIZER: std::sync::OnceLock<UrlLocalizer> = std::sync::OnceLock::new();

/// Get the global URL localizer instance
pub fn url_localizer() -> &'static UrlLocalizer {
    URL_LOCALIZER.get_or_init(UrlLocalizer::new)
}

/// Convenience function to localize a URL
pub fn localize_url(path: &str, target_lang: &str) -> String {
    url_localizer().localize_url(path, target_lang)
}

/// Convenience function to extract language from URL
pub fn extract_language(path: &str) -> &str {
    url_localizer().extract_language(path)
}

/// Convenience function to get clean path
pub fn clean_path(path: &str) -> String {
    url_localizer().clean_path(path)
}

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

    #[test]
    fn test_english_urls() {
        let localizer = UrlLocalizer::new();

        assert_eq!(localizer.localize_url("/", "en"), "/");
        assert_eq!(localizer.localize_url("/about", "en"), "/about");
        assert_eq!(localizer.localize_url("/services", "en"), "/services");
        assert_eq!(localizer.localize_url("/es/about", "en"), "/about");
        assert_eq!(localizer.localize_url("/es/servicios", "en"), "/services");
    }

    #[test]
    fn test_spanish_urls() {
        let localizer = UrlLocalizer::new();

        assert_eq!(localizer.localize_url("/", "es"), "/es");
        assert_eq!(localizer.localize_url("/about", "es"), "/es/sobre-mi");
        assert_eq!(localizer.localize_url("/services", "es"), "/es/servicios");
        assert_eq!(localizer.localize_url("/contact", "es"), "/es/contactar");
        assert_eq!(
            localizer.localize_url("/work-request", "es"),
            "/es/solicitud-trabajo"
        );
        // Content type routes are tested through the routing system
    }

    #[test]
    fn test_language_extraction() {
        let localizer = UrlLocalizer::new();

        assert_eq!(localizer.extract_language("/"), "en");
        assert_eq!(localizer.extract_language("/about"), "en");
        assert_eq!(localizer.extract_language("/es"), "es");
        assert_eq!(localizer.extract_language("/es/about"), "es");
        assert_eq!(localizer.extract_language("/es/servicios"), "es");
    }

    #[test]
    fn test_clean_path() {
        let localizer = UrlLocalizer::new();

        assert_eq!(localizer.clean_path("/"), "/");
        assert_eq!(localizer.clean_path("/about"), "/about");
        assert_eq!(localizer.clean_path("/es"), "/");
        assert_eq!(localizer.clean_path("/es/about"), "/about");
        assert_eq!(localizer.clean_path("/es/servicios"), "/servicios");
    }
}
