//! Menu Registry for Context-Based Menu Management
//!
//! This module provides the MenuRegistry type that stores all language menus
//! for instant access without HTTP requests. Used in conjunction with Leptos
//! context system for SSR-first architecture.

use std::collections::HashMap;

use rustelo_core_lib::defs::MenuItem;

/// Registry containing menus for all available languages
///
/// This is provided via Leptos context during SSR and hydration,
/// allowing instant menu access on language changes without HTTP calls.
#[derive(Clone, Debug)]
pub struct MenuRegistry {
    /// HashMap mapping language codes to their menu items
    /// e.g. "en" -> vec![MenuItem {...}, ...], "es" -> vec![MenuItem {...},
    /// ...]
    menus: HashMap<String, Vec<MenuItem>>,
}

impl MenuRegistry {
    /// Create a new empty MenuRegistry
    pub fn new() -> Self {
        Self {
            menus: HashMap::new(),
        }
    }

    /// Insert menu items for a language
    ///
    /// # Arguments
    /// * `lang` - Language code (e.g., "en", "es", "fr")
    /// * `items` - Vector of menu items for that language
    pub fn insert(&mut self, lang: impl Into<String>, items: Vec<MenuItem>) {
        self.menus.insert(lang.into(), items);
    }

    /// Get menu items for a language
    ///
    /// # Arguments
    /// * `lang` - Language code to retrieve
    ///
    /// # Returns
    /// * `Some(&Vec<MenuItem>)` if language exists
    /// * `None` if language not found
    pub fn get(&self, lang: &str) -> Option<&Vec<MenuItem>> {
        self.menus.get(lang)
    }

    /// Get menu items for a language (cloned)
    ///
    /// # Arguments
    /// * `lang` - Language code to retrieve
    ///
    /// # Returns
    /// * `Some(Vec<MenuItem>)` if language exists
    /// * `None` if language not found
    pub fn get_cloned(&self, lang: &str) -> Option<Vec<MenuItem>> {
        self.menus.get(lang).cloned()
    }

    /// Check if a language exists in the registry
    ///
    /// # Arguments
    /// * `lang` - Language code to check
    ///
    /// # Returns
    /// * `true` if language exists
    /// * `false` if language not found
    pub fn contains_language(&self, lang: &str) -> bool {
        self.menus.contains_key(lang)
    }

    /// Get list of available languages
    ///
    /// # Returns
    /// Vector of language codes
    pub fn available_languages(&self) -> Vec<String> {
        self.menus.keys().cloned().collect()
    }

    /// Get number of languages in registry
    pub fn language_count(&self) -> usize {
        self.menus.len()
    }

    /// Create from HashMap (useful for batch loading)
    pub fn from_map(menus: HashMap<String, Vec<MenuItem>>) -> Self {
        Self { menus }
    }

    /// Get internal HashMap reference
    pub fn menus(&self) -> &HashMap<String, Vec<MenuItem>> {
        &self.menus
    }

    /// Convert to HashMap
    pub fn into_map(self) -> HashMap<String, Vec<MenuItem>> {
        self.menus
    }
}

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

/// Error type for menu registry operations
#[derive(Debug, Clone)]
pub enum MenuRegistryError {
    /// Language not found in registry
    LanguageNotFound(String),
    /// Failed to load menus
    LoadError(String),
}

impl std::fmt::Display for MenuRegistryError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::LanguageNotFound(lang) => {
                write!(f, "Language '{}' not found in menu registry", lang)
            }
            Self::LoadError(msg) => write!(f, "Failed to load menus: {}", msg),
        }
    }
}

impl std::error::Error for MenuRegistryError {}
