//! Modern routing engine
//!
//! This module contains the core routing logic that works entirely with
//! TOML-based configuration and supports dynamic language detection.

// Submodules
pub mod content;
pub mod factory;
pub mod global;
pub mod navigation;
pub mod parameters;
pub mod resolver;
pub mod types;

// Re-export key types and functions
use std::collections::HashMap;

pub use global::{
    get_language_switch_url, get_menu_navigation, get_route_breadcrumbs, get_routing_engine,
    get_routing_engine_mut, get_sitemap_routes, get_toml_routes_for_language, is_valid_route,
    resolve_route, resolve_unified_route,
};
pub use types::{NavigationItem, NavigationTarget, RouteMetadata, RouteResolution};

use crate::routing::components::{RouteConfigToml, RoutesConfig};
use crate::routing::config::get_routing_config;
use crate::routing::utils::extract_lang_and_path;

/// Modern routing engine with TOML configuration
pub struct RoutingEngine {
    /// TOML-based route configuration
    toml_config: RoutesConfig,
    /// Cached navigation items by language
    navigation_cache: HashMap<String, Vec<NavigationItem>>,
    /// Cached route resolutions by (path, language) key
    resolution_cache: std::sync::Arc<std::sync::RwLock<HashMap<(String, String), RouteResolution>>>,
}

impl RoutingEngine {
    /// Create a new routing engine
    pub fn new() -> Self {
        let toml_config = get_routing_config().clone();

        Self {
            toml_config,
            navigation_cache: HashMap::new(),
            resolution_cache: std::sync::Arc::new(std::sync::RwLock::new(HashMap::new())),
        }
    }

    /// Resolve a path to a route with complete metadata
    pub fn resolve_unified_route(&self, path: &str) -> RouteResolution {
        // Extract language for cache key
        let (language, _) = extract_lang_and_path(path);
        let cache_key = (path.to_string(), language.clone());

        // Check cache first
        if let Ok(cache) = self.resolution_cache.read() {
            if let Some(cached_resolution) = cache.get(&cache_key) {
                return cached_resolution.clone();
            }
        }

        // Resolve using existing logic
        let resolution = resolver::resolve_unified_route(&self.toml_config, path);

        // Cache the result if it exists (successful resolution)
        if resolution.exists {
            if let Ok(mut cache) = self.resolution_cache.write() {
                cache.insert(cache_key, resolution.clone());
            }
        }

        resolution
    }

    /// Clear the resolution cache (useful when routes change)
    pub fn clear_resolution_cache(&self) {
        if let Ok(mut cache) = self.resolution_cache.write() {
            cache.clear();
        }
    }

    /// Get navigation items for a language
    pub fn get_navigation_items(&mut self, language: &str) -> Vec<NavigationItem> {
        navigation::generate_navigation_items(
            &self.toml_config,
            language,
            &mut self.navigation_cache,
        )
    }

    /// Check if a route exists in the TOML configuration
    pub fn route_exists(&self, path: &str) -> bool {
        self.toml_config.routes.iter().any(|route| {
            route.enabled
                && (route.path == path || {
                    let (_, clean_path) = extract_lang_and_path(path);
                    route.path == clean_path
                })
        })
    }

    /// Get all routes for sitemap generation
    pub fn get_sitemap_routes(&self) -> Vec<&RouteConfigToml> {
        self.toml_config
            .routes
            .iter()
            .filter(|route| route.enabled && route.is_visible_in_sitemap())
            .collect()
    }

    /// Get TOML routes for a specific language
    pub fn get_toml_routes_for_language(&self, language: &str) -> Vec<&RouteConfigToml> {
        self.toml_config
            .routes
            .iter()
            .filter(|route| route.enabled && route.language == language)
            .collect()
    }
}

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