//! Meta Configuration Preloader
//!
//! Preloads all meta configurations at app startup to ensure emojis are
//! available immediately during SPA navigation, eliminating the async loading
//! race condition.

use std::collections::HashMap;
use std::sync::{Arc, LazyLock, RwLock};
use std::time::Duration;

#[cfg(target_arch = "wasm32")]
use wasm_bindgen_futures::spawn_local;

use crate::categories::{load_meta_config, MetaConfig};
use crate::config::get_supported_languages;

/// Meta configuration loading states
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum MetaLoadingState {
    NotStarted,
    Loading,
    Loaded,
    Failed,
}

/// Global meta config cache (non-reactive)
static META_CONFIG_CACHE: LazyLock<Arc<RwLock<HashMap<String, MetaConfig>>>> =
    LazyLock::new(|| Arc::new(RwLock::new(HashMap::new())));

/// Global loading state (non-reactive)
static META_LOADING_STATE: LazyLock<Arc<RwLock<MetaLoadingState>>> =
    LazyLock::new(|| Arc::new(RwLock::new(MetaLoadingState::NotStarted)));

/// Initialize meta config preloader - call this during app startup (client-side
/// only)
#[cfg(all(target_arch = "wasm32", not(feature = "ssr")))]
pub fn init_meta_preloader() {
    // Set loading state
    if let Ok(mut state) = (*META_LOADING_STATE).write() {
        *state = MetaLoadingState::Loading;
    }

    spawn_local(async move {
        let supported_languages = get_supported_languages();
        let content_types = crate::content_resolver::get_available_content_types();

        let mut all_configs = HashMap::new();
        let mut loading_failed = false;

        for content_type in &content_types {
            for language in supported_languages.iter() {
                let cache_key = format!("{}:{}", content_type, language);

                // Try to load the config multiple times with increasing delays
                let mut loaded = false;
                for attempt in 0..8 {
                    // Increase attempts for better reliability
                    let delay_ms = 100 + (attempt * 200); // 100ms, 300ms, 500ms, etc.

                    // Wait before trying to load
                    gloo_timers::future::sleep(Duration::from_millis(delay_ms as u64)).await;

                    // Try to load the config
                    if let Ok(config) = load_meta_config(content_type, language) {
                        all_configs.insert(cache_key.clone(), config);
                        loaded = true;
                        tracing::debug!(
                            "Successfully preloaded meta config for {}/{}",
                            content_type,
                            language
                        );
                        break;
                    }
                }

                if !loaded {
                    tracing::warn!(
                        "Failed to preload meta config for {}/{} after multiple attempts",
                        content_type,
                        language
                    );
                    loading_failed = true;
                }
            }
        }

        // Update the cache
        if let Ok(mut cache) = (*META_CONFIG_CACHE).write() {
            *cache = all_configs;
        }

        // Update the loading state
        if let Ok(mut state) = (*META_LOADING_STATE).write() {
            *state = if loading_failed {
                MetaLoadingState::Failed
            } else {
                MetaLoadingState::Loaded
            };
        }

        tracing::info!(
            "Meta config preloading completed with state: {:?}",
            if loading_failed {
                MetaLoadingState::Failed
            } else {
                MetaLoadingState::Loaded
            }
        );
    });
}

/// Initialize meta config preloader for SSR - loads configs synchronously
#[cfg(any(not(target_arch = "wasm32"), feature = "ssr"))]
pub fn init_meta_preloader() {
    // SSR: Load meta configs synchronously
    let supported_languages = get_supported_languages();
    let content_types = crate::content_resolver::get_available_content_types();

    let mut all_configs = HashMap::new();
    let mut loading_failed = false;

    for content_type in &content_types {
        for language in supported_languages.iter() {
            let cache_key = format!("{}:{}", content_type, language);

            // Try to load the config synchronously
            if let Ok(config) = load_meta_config(content_type, language) {
                all_configs.insert(cache_key.clone(), config);
                tracing::debug!(
                    "Successfully preloaded meta config for {}/{}",
                    content_type,
                    language
                );
            } else {
                tracing::warn!(
                    "Failed to preload meta config for {}/{}",
                    content_type,
                    language
                );
                loading_failed = true;
            }
        }
    }

    // Update the cache
    if let Ok(mut cache) = (*META_CONFIG_CACHE).write() {
        *cache = all_configs;
    }

    // Update the loading state
    if let Ok(mut state) = (*META_LOADING_STATE).write() {
        *state = if loading_failed {
            MetaLoadingState::Failed
        } else {
            MetaLoadingState::Loaded
        };
    }

    tracing::info!(
        "SSR meta config preloading completed with state: {:?}",
        if loading_failed {
            MetaLoadingState::Failed
        } else {
            MetaLoadingState::Loaded
        }
    );
}

/// Get cached meta config if available, otherwise return None
pub fn get_cached_meta_config(content_type: &str, language: &str) -> Option<MetaConfig> {
    let cache_key = format!("{}:{}", content_type, language);
    if let Ok(cache) = (*META_CONFIG_CACHE).read() {
        cache.get(&cache_key).cloned()
    } else {
        None
    }
}

/// Get emoji for category - returns the emoji string directly
pub fn get_category_emoji(content_type: &str, language: &str, category: &str) -> String {
    // During WASM hydration, ensure consistent behavior by checking loading state
    #[cfg(target_arch = "wasm32")]
    {
        // If configs are not fully loaded, always return consistent fallback
        if !are_meta_configs_loaded() {
            return "📄".to_string(); // Generic document emoji for all content
                                     // types
        }
    }

    // Try to get from cache first (SSR or after WASM loading completes)
    if let Some(config) = get_cached_meta_config(content_type, language) {
        // Try exact match first
        if let Some(emoji) = config.categories_emojis.get(category) {
            return emoji.clone();
        }

        // Try lowercase match
        let category_lower = category.to_lowercase();
        for (key, emoji) in &config.categories_emojis {
            if key.to_lowercase() == category_lower {
                return emoji.clone();
            }
        }

        // Try partial match
        for (key, emoji) in &config.categories_emojis {
            if category_lower.contains(&key.to_lowercase())
                || key.to_lowercase().contains(&category_lower)
            {
                return emoji.clone();
            }
        }
    }

    // Fallback to generic emoji if config not loaded or category not found
    "📄".to_string()
}

/// Get emoji for tag - returns the emoji string directly
pub fn get_tag_emoji(content_type: &str, language: &str, tag: &str) -> String {
    // During WASM hydration, ensure consistent behavior by checking loading state
    #[cfg(target_arch = "wasm32")]
    {
        // If configs are not fully loaded, always return consistent fallback
        if !are_meta_configs_loaded() {
            return "🏷️".to_string();
        }
    }

    // Try to get from cache first (SSR or after WASM loading completes)
    if let Some(config) = get_cached_meta_config(content_type, language) {
        // Try exact match first
        if let Some(emoji) = config.tags_emojis.get(tag) {
            return emoji.clone();
        }

        // Try lowercase match
        let tag_lower = tag.to_lowercase();
        for (key, emoji) in &config.tags_emojis {
            if key.to_lowercase() == tag_lower {
                return emoji.clone();
            }
        }

        // Try partial match
        for (key, emoji) in &config.tags_emojis {
            if tag_lower.contains(&key.to_lowercase()) || key.to_lowercase().contains(&tag_lower) {
                return emoji.clone();
            }
        }
    }

    // Fallback to default tag emoji
    "🏷️".to_string()
}

/// Check if meta configs are loaded
pub fn are_meta_configs_loaded() -> bool {
    if let Ok(state) = (*META_LOADING_STATE).read() {
        *state == MetaLoadingState::Loaded
    } else {
        false
    }
}

/// Force refresh meta configs (useful for development)
#[cfg(target_arch = "wasm32")]
pub fn refresh_meta_configs() {
    tracing::info!("Forcing meta config refresh");

    // Clear cache and restart loading
    if let Ok(mut cache) = (*META_CONFIG_CACHE).write() {
        cache.clear();
    }
    if let Ok(mut state) = (*META_LOADING_STATE).write() {
        *state = MetaLoadingState::NotStarted;
    }

    // Restart preloader
    init_meta_preloader();
}

/// Force refresh meta configs for non-WASM (no-op)
#[cfg(not(target_arch = "wasm32"))]
pub fn refresh_meta_configs() {
    // No-op for server-side
}
