// Unified i18n system that works identically in both SSR and client contexts
// Now fully language-agnostic using dynamic language discovery
use crate::fluent::content_loader::load_texts_from_ftl;
use crate::i18n::page_translator::PageTranslator;
use crate::Texts;
use leptos::prelude::*;
use std::collections::HashMap;

/// Unified i18n struct that provides consistent translation functionality
/// in both SSR and client environments
#[derive(Clone, Debug, PartialEq)]
pub struct UnifiedI18n {
    pub language: String,
    pub translations: Texts,
}

impl UnifiedI18n {
    /// Create new UnifiedI18n instance with pre-loaded translations
    /// This works synchronously in both SSR and client contexts
    pub fn new(language: &str, _initial_path: &str) -> Self {
        let translations = load_translations_sync(language);
        Self {
            language: language.to_string(),
            translations,
        }
    }

    /// Get translation for a key in the current language
    pub fn t(&self, key: &str) -> String {
        let translations = self
            .translations
            .get_translations_for_language(&self.language);

        translations.get(key).cloned().unwrap_or_else(|| {
            // Return key in brackets to indicate missing translation
            format!("[{key}]")
        })
    }

    /// Get current language code
    pub fn lang_code(&self) -> &str {
        &self.language
    }

    /// Create localized URL based on current language - now language-agnostic
    pub fn localized_url(&self, path: &str) -> String {
        // Use the language-agnostic URL localizer
        crate::i18n::urls::localize_url(path, &self.language)
    }

    /// Check if current language is not the default language
    pub fn is_non_default_language(&self) -> bool {
        self.language != crate::i18n::discovery::get_default_language()
    }

    /// Check if this language is supported by the system
    pub fn is_supported_language(&self) -> bool {
        crate::i18n::discovery::is_supported_language(&self.language)
    }
}

/// Implementation of PageTranslator trait for UnifiedI18n
impl PageTranslator for UnifiedI18n {
    fn t(&self, key: &str) -> String {
        self.t(key)
    }

    fn localized_url(&self, path: &str) -> String {
        self.localized_url(path)
    }

    fn lang_code(&self) -> String {
        self.lang_code().to_string()
    }
}

/// Conditional console log for development - always enabled in debug builds
#[cfg(target_arch = "wasm32")]
macro_rules! debug_console_log {
    ($($arg:tt)*) => {
        #[cfg(debug_assertions)]
        {
            web_sys::console::log_1(&format!($($arg)*).into());
        }
    };
}

/// Load translations synchronously for both SSR and client
/// This ensures both environments have identical translation data
fn load_translations_sync(language: &str) -> Texts {
    #[cfg(target_arch = "wasm32")]
    debug_console_log!(
        "🔄 load_translations_sync: Loading for language '{}'",
        language
    );

    // Use thread_local cache to avoid re-loading the same multi-language FTL data
    thread_local! {
        static CACHED_ALL_TEXTS: std::cell::RefCell<Option<Texts>> = const { std::cell::RefCell::new(None) };
    }

    CACHED_ALL_TEXTS.with(|cache| {
        let mut cache_ref = cache.borrow_mut();

        // Load the multi-language FTL data once
        if cache_ref.is_none() {
            #[cfg(target_arch = "wasm32")]
            debug_console_log!("🔄 load_translations_sync: First-time loading FTL data...");

            match load_texts_from_ftl("") {  // Pass empty string to load ALL languages
                Ok(all_texts) => {
                    #[cfg(target_arch = "wasm32")]
                    debug_console_log!("✅ load_translations_sync: Loaded multi-language FTL data with {} languages", all_texts.translations.len());
                    *cache_ref = Some(all_texts);
                },
                Err(e) => {
                    tracing::error!("Failed to load FTL data: {}", e);
                    #[cfg(target_arch = "wasm32")]
                    debug_console_log!("❌ load_translations_sync: Failed to load FTL data: {}", e);

                    // Return empty translations - pages should handle missing keys gracefully
                    return crate::defs::Texts::default();
                }
            }
        }

        // Extract language-specific data from the cached multi-language FTL
        if let Some(ref all_texts) = *cache_ref {
            let lang_keys = all_texts.get_translations_for_language(language);

            #[cfg(target_arch = "wasm32")]
            {
                debug_console_log!("✅ load_translations_sync: Extracted {} keys for language '{}'", lang_keys.len(), language);

                // Sample a few keys for debugging
                let sample_keys: Vec<String> = lang_keys.keys().take(3).cloned().collect();
                debug_console_log!("📋 load_translations_sync: Sample keys: {:?}", sample_keys);

                // Debug: Show actual content values to see if they differ by language
                if let Some(title) = lang_keys.get("home-hero-title") {
                    debug_console_log!("🔍 load_translations_sync[{}]: home-hero-title = '{}'", language, title);
                }
                if let Some(subtitle) = lang_keys.get("home-hero-subtitle") {
                    debug_console_log!("🔍 load_translations_sync[{}]: home-hero-subtitle = '{}'", language, subtitle);
                }

                // Debug: Show total available languages in cache
                debug_console_log!("🗂️ load_translations_sync: Total languages in cache: {}", all_texts.translations.len());
                let cache_langs: Vec<String> = all_texts.translations.keys().cloned().collect();
                debug_console_log!("🗂️ load_translations_sync: Cache languages: {:?}", cache_langs);
            }

            // Create a language-specific Texts object containing only the requested language
            crate::defs::Texts::from_language_maps(vec![(language.to_string(), lang_keys)])
        } else {
            crate::defs::Texts::default()
        }
    })
}

/// Detect language from URL path using dynamic language discovery and route configurations
pub fn detect_language_from_path(path: &str) -> String {
    let discovered_languages = crate::i18n::discovery::discover_available_languages();

    // Check if path starts with any discovered language prefix
    if let Some(lang_part) = path.strip_prefix('/').and_then(|p| p.split('/').next()) {
        if discovered_languages.contains(&lang_part.to_string()) {
            // Check if this is a valid language in our routing config
            if !crate::routing::config::get_routes_for_language(lang_part).is_empty() {
                return lang_part.to_string();
            }
        }
    }

    // Check if this path exists as a non-default route
    let config = crate::routing::config::get_routing_config();
    let default_lang = crate::i18n::discovery::get_default_language();

    for route in &config.routes {
        if route.enabled && route.path == path && route.language != default_lang {
            return route.language.clone();
        }
    }

    // Default to discovered default language
    default_lang.to_string()
}

/// Context key for UnifiedI18n
#[derive(Clone, Copy)]
pub struct UnifiedI18nContext;

/// Hook to use unified i18n in components
/// This works safely in both SSR and client contexts
pub fn use_unified_i18n() -> UnifiedI18n {
    // Try to get from context first
    if let Some(i18n) = use_context::<UnifiedI18n>() {
        return i18n;
    }

    // Fallback: create a default i18n instance using discovered default language
    // This ensures components always have access to translations
    UnifiedI18n::new(crate::i18n::discovery::get_default_language(), "/")
}

/// Provide unified i18n context for child components
pub fn provide_unified_i18n(i18n: UnifiedI18n) {
    provide_context(i18n);
}

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

    #[test]
    fn test_unified_i18n_creation() {
        let i18n = UnifiedI18n::new("en", "/");
        assert_eq!(i18n.lang_code(), "en");
        assert!(i18n.is_supported_language());
    }

    #[test]
    fn test_spanish_i18n() {
        let i18n = UnifiedI18n::new("es", "/es");
        assert_eq!(i18n.lang_code(), "es");
        assert!(i18n.is_supported_language());
        assert!(!i18n.is_non_default_language() || i18n.is_non_default_language());
        // Either can be true depending on system config
    }

    #[test]
    fn test_localized_urls() {
        let en_i18n = UnifiedI18n::new("en", "/");
        assert_eq!(en_i18n.localized_url("/"), "/");
        assert_eq!(en_i18n.localized_url("/contact"), "/contact");

        let es_i18n = UnifiedI18n::new("es", "/es");
        assert_eq!(es_i18n.localized_url("/"), "/es");
        assert_eq!(es_i18n.localized_url("/contact"), "/es/contactar");
    }

    #[test]
    fn test_translations() {
        let i18n = UnifiedI18n::new("en", "/");
        let title = i18n.t("not-found-title");

        // Should either get the FTL translation or the emergency fallback
        assert!(title == "Page Not Found" || title.starts_with("["));
    }

    #[test]
    fn test_language_detection() {
        let default_lang = crate::i18n::discovery::get_default_language();

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

        // Test with discovered languages
        let discovered = crate::i18n::discovery::discover_available_languages();
        for lang in discovered {
            if lang != default_lang {
                let path = format!("/{}", lang);
                let detected = detect_language_from_path(&path);
                // Should detect the language if it's in routing config
                assert!(detected == *lang || detected == default_lang);
            }
        }
    }
}
