//! Unified i18n helpers that work in both SSR and client contexts
//!
//! This module provides abstraction over the different i18n systems used
//! in client and SSR, allowing unified page components to work in both
//! contexts. Now fully language-agnostic using dynamic language discovery.

use std::collections::HashMap;

#[cfg(any(target_arch = "wasm32", feature = "leptos-hydration"))]
use leptos::prelude::*;

use crate::i18n::{t_for_language, PageTranslator};

/// Context-aware i18n interface that works in both SSR and client
pub struct UnifiedI18nContext;

impl UnifiedI18nContext {
    /// Get translated text - works in both SSR and client contexts
    #[cfg(target_arch = "wasm32")]
    pub fn t(&self, key: &str) -> String {
        // Client-side: This will be called from client crate,
        // so it should use the client's i18n system directly
        // For now, return placeholder - will be implemented when used
        format!("[CLIENT:{}]", key)
    }

    #[cfg(not(target_arch = "wasm32"))]
    pub fn t(&self, key: &str) -> String {
        // SSR: This will be called from SSR crate,
        // so it should use the SSR's i18n system directly
        // For now, return placeholder - will be implemented when used
        format!("[SSR:{key}]")
    }

    /// Create localized URL - works in both SSR and client contexts
    #[cfg(target_arch = "wasm32")]
    pub fn localized_url(&self, path: &str) -> String {
        // Client-side: will be implemented in client context
        let default_lang = crate::i18n::discovery::get_default_language();
        self.localize_path(path, default_lang)
    }

    #[cfg(not(target_arch = "wasm32"))]
    pub fn localized_url(&self, path: &str) -> String {
        // SSR: basic localization logic
        let default_lang = crate::i18n::discovery::get_default_language();
        self.localize_path(path, default_lang)
    }

    /// Get current language code
    #[cfg(target_arch = "wasm32")]
    pub fn lang_code(&self) -> String {
        // Client-side: will be implemented in client context
        crate::i18n::discovery::get_default_language().to_string()
    }

    #[cfg(not(target_arch = "wasm32"))]
    pub fn lang_code(&self) -> String {
        // SSR: would need to be determined from context/path
        crate::i18n::discovery::get_default_language().to_string()
    }

    /// Helper for path localization (works in both contexts) - now
    /// language-agnostic
    fn localize_path(&self, path: &str, language: &str) -> String {
        // Use the URL localizer which is now language-agnostic
        crate::i18n::urls::localize_url(path, language)
    }
}

/// Create a unified i18n context that works in both environments
pub fn create_unified_i18n() -> UnifiedI18nContext {
    UnifiedI18nContext
}

/// Unified localization helper with language-aware methods
pub struct UnifiedLocalizationHelper {
    language: String,
}

impl UnifiedLocalizationHelper {
    /// Create helper with specific language
    pub fn new(language: String) -> Self {
        Self { language }
    }

    /// Get translated text for specific language
    pub fn t(&self, key: &str) -> String {
        #[cfg(target_arch = "wasm32")]
        {
            // On client, placeholder for now
            format!("[CLIENT:{}:{}]", self.language, key)
        }

        #[cfg(not(target_arch = "wasm32"))]
        {
            // On SSR, placeholder for now
            format!("[SSR:{}:{}]", self.language, key)
        }
    }

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

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

/// Implement PageTranslator trait for UnifiedLocalizationHelper
impl PageTranslator for UnifiedLocalizationHelper {
    fn t(&self, key: &str) -> String {
        #[cfg(target_arch = "wasm32")]
        {
            // On client, use actual translation function
            t_for_language(&self.language, key)
        }

        #[cfg(not(target_arch = "wasm32"))]
        {
            // On SSR, use actual translation function
            t_for_language(&self.language, key)
        }
    }

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

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

/// Build page content from key list using current language
///
/// This is the core function that enables language-agnostic content loading.
/// It takes a PageTranslator (which knows the current language) and a list of
/// keys, then builds a HashMap with translations for the current language.
///
/// # Arguments
/// * `translator` - PageTranslator implementation (SSR or client)
/// * `keys` - Array of FTL keys to load
///
/// # Returns
/// HashMap with keys mapped to their translated values
///
/// # Example
/// ```rust
/// let content = build_page_content(&i18n, &["home-title", "home-subtitle"]);
/// // Returns: {"home-title": "Welcome", "home-subtitle": "To my site"}
/// ```
pub fn build_page_content<T: PageTranslator>(
    translator: &T,
    keys: &[&str],
) -> HashMap<String, String> {
    keys.iter()
        .map(|key| (key.to_string(), translator.t(key)))
        .collect()
}

/// Build page content using pattern-based key discovery (ZERO MAINTENANCE!)
///
/// This function dynamically discovers all keys matching one or more patterns
/// from the i18n bundle, eliminating the need to maintain hardcoded key lists.
/// This is the single source of truth solution.
///
/// # Arguments
/// * `translator` - PageTranslator implementation (SSR or client)
/// * `patterns` - Single prefix pattern or array of prefix patterns
///   - Single: `"home-"`
///   - Multiple: `&["home-", "nav-", "footer-"]`
///
/// # Returns
/// HashMap with all matching keys and their translated values
///
/// # Examples
/// ```rust
/// // Single prefix - discovers ALL keys starting with "home-" automatically
/// let content = build_page_content_patterns(&i18n, &["home-"]);
///
/// // Multiple prefixes - discovers keys from multiple sections
/// let content = build_page_content_patterns(&i18n, &["home-", "nav-", "footer-"]);
/// // Returns: {"home-title": "Welcome", "nav-menu": "Menu", "footer-copyright": "© 2025", ...}
///
/// // Add new key "home-feature" to FTL file → automatically included!
/// ```
///
/// # Benefits
/// - ✅ Zero maintenance - add FTL key to any section, it works immediately
/// - ✅ Single source of truth - only FTL files contain keys
/// - ✅ PREFIX-ONLY matching - no suffix hardcoding needed
/// - ✅ Single or multiple prefixes - flexible usage patterns
/// - ✅ Dynamic - discovers keys at runtime from actual i18n data
pub fn build_page_content_patterns<T: PageTranslator>(
    translator: &T,
    patterns: &[&str],
) -> HashMap<String, String> {
    // Get current language to determine which key set to search
    let _lang_code = translator.lang_code();

    // Access available keys from the translation system for all patterns
    let available_keys = discover_keys_for_patterns(translator, patterns);

    // Build content HashMap with discovered keys
    available_keys
        .iter()
        .map(|key| (key.clone(), translator.t(key)))
        .collect()
}

/// Discover all available keys matching multiple patterns from the translation
/// system
///
/// TRUE Zero-Maintenance Approach: directly access loaded FTL keys and filter
/// by multiple patterns. No hardcoded lists - discovers keys from the actual
/// translation data!
fn discover_keys_for_patterns<T: PageTranslator>(translator: &T, patterns: &[&str]) -> Vec<String> {
    use tracing::debug;

    debug!(
        "🔍 Starting TRUE zero-maintenance pattern discovery for patterns {:?} in language '{}'",
        patterns,
        translator.lang_code()
    );

    // Access the cached translations directly from the modern FTL system
    let language = translator.lang_code();

    // Use thread_local to access the same cache that t_for_language uses
    thread_local! {
        static CACHED_TRANSLATIONS: std::cell::RefCell<std::collections::HashMap<String, std::collections::HashMap<String, String>>> = std::cell::RefCell::new(std::collections::HashMap::new());
    }

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

        // Ensure translations are loaded for this language.
        // Primary: FTL_REGISTRY populated at startup by register_contributor.
        // Fallback: filesystem loader for standalone/test contexts.
        if !cache_ref.contains_key(&language) {
            if let Some(lang_map) = crate::registration::get_parsed_ftl_for_language(&language) {
                if !lang_map.is_empty() {
                    cache_ref.insert(language.clone(), lang_map);
                }
            }
            if !cache_ref.contains_key(&language) {
                match crate::fluent::content_loader::load_texts_from_ftl(&language) {
                    Ok(texts) => {
                        let lang_map = texts.get_translations_for_language(&language);
                        cache_ref.insert(language.clone(), lang_map);
                    }
                    Err(_) => {
                        cache_ref.insert(language.clone(), std::collections::HashMap::new());
                    }
                }
            }
        }

        if let Some(translations) = cache_ref.get(&language) {
            // Filter all actual keys by ALL patterns - TRUE zero maintenance!
            let mut discovered_keys: Vec<String> = Vec::new();

            for pattern in patterns {
                let pattern_keys: Vec<String> = translations
                    .keys()
                    .filter(|key| key.starts_with(pattern))
                    .cloned()
                    .collect();

                debug!(
                    "🎯 Pattern '{}': found {} keys",
                    pattern,
                    pattern_keys.len()
                );
                discovered_keys.extend(pattern_keys);
            }

            // Remove duplicates while preserving order
            discovered_keys.sort();
            discovered_keys.dedup();

            debug!(
                "🎯 TRUE zero-maintenance discovery complete: found {} total unique keys for \
                 patterns {:?} from {} total translations",
                discovered_keys.len(),
                patterns,
                translations.len()
            );

            if discovered_keys.is_empty() {
                debug!("⚠️ Not found keys: {:?}", &patterns);
                //  debug!("✅ Found keys: {:?}", discovered_keys);
            }

            discovered_keys
        } else {
            debug!("⚠️ No translations found for language '{}'", language);
            vec![]
        }
    })
}
