use std::collections::HashMap;

use super::traits::*;

/// Route mapping for content resolution
pub struct RouteMap {
    pub patterns: HashMap<String, RouteDefinition>,
}

#[derive(Debug, Clone)]
pub struct RouteDefinition {
    pub id: String,
    pub path_pattern: String,
    pub content_kind: Option<String>,
    pub component: String,
    pub dynamic: bool,
    pub enabled: bool,
}

/// Universal content resolver for URL direct access and SPA navigation
pub struct ContentResolver {
    pub kinds: ContentKindRegistry,
    pub route_map: RouteMap,
    pub available_languages: Vec<String>,
}

impl ContentResolver {
    pub fn new() -> Self {
        Self {
            kinds: ContentKindRegistry::new(),
            route_map: RouteMap {
                patterns: HashMap::new(),
            },
            available_languages: vec!["en".to_string(), "es".to_string()],
        }
    }

    /// Resolves content from URL direct access or SPA navigation
    pub fn resolve(&self, path: &str, mode: LoadMode) -> ContentResolution {
        match mode {
            LoadMode::Direct => self.resolve_direct_url(path),
            LoadMode::SPA => self.resolve_spa_navigation(path),
        }
    }

    /// Resolves content from direct URL access
    pub fn resolve_direct_url(&self, path: &str) -> ContentResolution {
        let language = self.detect_language(path);
        let content_kind = self.detect_content_kind(path);

        ContentResolution {
            content_type: content_kind.unwrap_or("content".to_string()),
            language,
            path: path.to_string(),
            metadata: None,
        }
    }

    /// Resolves content from SPA navigation
    pub fn resolve_spa_navigation(&self, path: &str) -> ContentResolution {
        // Same logic for now, but can be extended for SPA-specific behavior
        self.resolve_direct_url(path)
    }

    /// Detects language automatically without hardcoded references
    pub fn detect_language(&self, path: &str) -> String {
        let segments: Vec<&str> = path.trim_start_matches('/').split('/').collect();

        if let Some(first_segment) = segments.first() {
            if self
                .available_languages
                .contains(&first_segment.to_string())
            {
                return first_segment.to_string();
            }
        }

        // Default to first available language (usually English)
        self.available_languages
            .first()
            .unwrap_or(&"en".to_string())
            .clone()
    }

    /// Determines content_kind from the route
    pub fn detect_content_kind(&self, path: &str) -> Option<String> {
        let segments: Vec<&str> = path.trim_start_matches('/').split('/').collect();

        // Skip language segment if present
        let start_idx =
            if segments.len() > 1 && self.available_languages.contains(&segments[0].to_string()) {
                1
            } else {
                0
            };

        if let Some(kind_segment) = segments.get(start_idx) {
            if self.kinds.get(kind_segment).is_some() {
                return Some(kind_segment.to_string());
            }
        }

        // Default to base content kind
        Some("content".to_string())
    }

    /// Extracts slug from path
    pub fn extract_slug(&self, path: &str) -> Option<String> {
        let segments: Vec<&str> = path.trim_start_matches('/').split('/').collect();

        // Skip language and content_kind segments
        let start_idx =
            if segments.len() > 1 && self.available_languages.contains(&segments[0].to_string()) {
                2 // Skip lang and content_kind
            } else {
                1 // Skip content_kind only
            };

        segments.get(start_idx).map(|s| s.to_string())
    }

    /// Builds content path for specific language and kind
    pub fn build_path(&self, language: &str, content_kind: &str, slug: Option<&str>) -> String {
        let mut path = if language
            == self
                .available_languages
                .first()
                .unwrap_or(&"en".to_string())
        {
            String::new() // No language prefix for default language
        } else {
            format!("/{}", language)
        };

        path.push_str(&format!("/{}", content_kind));

        if let Some(slug) = slug {
            path.push_str(&format!("/{}", slug));
        }

        path
    }

    /// Registers a content kind
    pub fn register_kind(&mut self, config: ContentConfig) {
        self.kinds.register(config);
    }

    /// Sets available languages dynamically
    pub fn set_available_languages(&mut self, languages: Vec<String>) {
        self.available_languages = languages;
    }
}

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

#[cfg(test)]
mod tests {
    use super::*;
    // use crate::content::traits::ContentFeatures;

    #[test]
    fn test_language_detection() {
        let resolver = ContentResolver::new();

        assert_eq!(resolver.detect_language("/"), "en");
        assert_eq!(resolver.detect_language("/es/content"), "es");
        assert_eq!(resolver.detect_language("/content"), "en");
        assert_eq!(resolver.detect_language("/es/recetas/item"), "es");
    }

    #[test]
    fn test_content_kind_detection() {
        let mut resolver = ContentResolver::new();

        // Register some content kinds
        resolver.register_kind(ContentConfig {
            name: "content".to_string(),
            directory: "content".to_string(),
            enabled: true,
            is_default: None,
            specialized: None,
            features: ContentFeatures {
                style_mode: "row".to_string(),
                style_css: "content-content".to_string(),
                use_feature: true,
                use_categories: true,
                use_tags: true,
                use_emojis: false,
                cta_view: "BlogCTAView".to_string(),
                default_page_size: Some(12),
                page_size_options: Some(vec![6, 12, 24, 48]),
                show_page_info: Some(true),
                pagination_style: Some("numbered".to_string()),
                show_difficulty: None,
                show_duration: None,
                show_prerequisites: None,
            },
        });

        assert_eq!(
            resolver.detect_content_kind("/content/post"),
            Some("content".to_string())
        );
        assert_eq!(
            resolver.detect_content_kind("/es/content/post"),
            Some("content".to_string())
        );
        assert_eq!(
            resolver.detect_content_kind("/unknown"),
            Some("content".to_string())
        );
    }

    #[test]
    fn test_path_building() {
        let resolver = ContentResolver::new();

        assert_eq!(resolver.build_path("en", "content", None), "/content");
        assert_eq!(resolver.build_path("es", "content", None), "/es/content");
        assert_eq!(
            resolver.build_path("en", "content", Some("post")),
            "/content/post"
        );
        assert_eq!(
            resolver.build_path("es", "recetas", Some("item")),
            "/es/recetas/item"
        );
    }

    #[test]
    fn test_content_resolution() {
        let resolver = ContentResolver::new();

        let direct = resolver.resolve("/content/post", LoadMode::Direct);
        let spa = resolver.resolve("/content/post", LoadMode::SPA);

        assert_eq!(direct.content_type, spa.content_type);
        assert_eq!(direct.language, "en");
        assert_eq!(direct.content_type, "content");
    }
}
