//! Path Resolution Module for PostViewer
//!
//! Consolidated path extraction and parameter resolution using shared routing
//! utilities. Eliminates duplication by leveraging existing routing
//! infrastructure.

/// Path parameter extraction results
#[derive(Debug, Clone)]
pub struct ExtractedParams {
    pub slug: Option<String>,
    pub category: Option<String>,
}

/// Unified path resolver using shared routing utilities
pub struct PathResolver;

impl PathResolver {
    /// Extract both slug and category from path using shared routing utilities
    /// This replaces the duplicated extract_slug_and_category_from_path
    /// function
    pub fn extract_parameters(path: &str) -> ExtractedParams {
        // Use the correct routing utils path
        let config = rustelo_core_lib::routing::utils::load_routes_config();

        // Try to extract parameters from known content route patterns
        for route in &config.routes {
            if route.enabled && route.path.contains("{slug}") {
                if let Some(params) =
                    rustelo_core_lib::routing::engine::parameters::extract_multiple_parameters(
                        &route.path,
                        path,
                    )
                {
                    let slug = params.get("slug").cloned();
                    let category = params.get("category").cloned();

                    #[cfg(target_arch = "wasm32")]
                    web_sys::console::log_1(
                        &format!(
                            "🔍 Path extraction: path='{}', pattern='{}', slug={:?}, category={:?}",
                            path, route.path, slug, category
                        )
                        .into(),
                    );

                    if slug.is_some() {
                        return ExtractedParams { slug, category };
                    }
                }
            }
        }

        // Fallback: extract from path structure manually
        Self::fallback_extraction(path)
    }

    /// Fallback extraction when routing patterns don't match
    fn fallback_extraction(path: &str) -> ExtractedParams {
        let path_clean = path.strip_suffix(".html").unwrap_or(path);
        let path_clean = path_clean.trim_start_matches('/');
        let parts: Vec<&str> = path_clean.split('/').filter(|p| !p.is_empty()).collect();

        match parts.len() {
            len if len >= 3 => {
                // Pattern: /content_type/category/slug
                let category = parts.get(parts.len() - 2).map(|s| s.to_string());
                let slug = parts.last().map(|s| s.to_string());
                ExtractedParams { slug, category }
            }
            len if len >= 2 => {
                // Pattern: /content_type/slug (no category)
                let slug = parts.last().map(|s| s.to_string());
                ExtractedParams {
                    slug,
                    category: None,
                }
            }
            _ => ExtractedParams {
                slug: None,
                category: None,
            },
        }
    }

    /// Extract just the slug from path (legacy compatibility)
    pub fn extract_slug(path: &str) -> Option<String> {
        Self::extract_parameters(path).slug
    }

    /// Validate that extracted parameters are reasonable
    pub fn validate_parameters(params: &ExtractedParams) -> bool {
        if let Some(ref slug) = params.slug {
            // Basic validation: slug should not be empty or just numbers
            !slug.is_empty() && !slug.chars().all(|c| c.is_ascii_digit())
        } else {
            false
        }
    }

    /// Get slug and category with validation
    pub fn get_validated_parameters(path: &str) -> Option<ExtractedParams> {
        let params = Self::extract_parameters(path);
        if Self::validate_parameters(&params) {
            Some(params)
        } else {
            None
        }
    }
}

/// Content path utilities
pub struct ContentPathUtils;

impl ContentPathUtils {
    /// Build content path from components
    pub fn build_path(
        content_type: &str,
        language: &str,
        category: Option<&str>,
        slug: &str,
    ) -> String {
        match category {
            Some(cat) => format!("/{}/{}/{}/{}", content_type, language, cat, slug),
            None => format!("/{}/{}/{}", content_type, language, slug),
        }
    }

    /// Build HTML path from components
    pub fn build_html_path(
        content_type: &str,
        language: &str,
        category: Option<&str>,
        slug: &str,
    ) -> String {
        let base_path = Self::build_path(content_type, language, category, slug);
        if base_path.ends_with(".html") {
            base_path
        } else {
            format!("{}.html", base_path)
        }
    }

    /// Extract content type from path
    pub fn extract_content_type(path: &str) -> Option<String> {
        let path_clean = path.trim_start_matches('/');
        let parts: Vec<&str> = path_clean.split('/').filter(|p| !p.is_empty()).collect();

        if !parts.is_empty() {
            Some(parts[0].to_string())
        } else {
            None
        }
    }

    /// Extract language from path
    pub fn extract_language(path: &str) -> Option<String> {
        let path_clean = path.trim_start_matches('/');
        let parts: Vec<&str> = path_clean.split('/').filter(|p| !p.is_empty()).collect();

        if parts.len() >= 2 {
            Some(parts[1].to_string())
        } else {
            None
        }
    }
}

/// Path analysis utilities for debugging and logging
#[cfg(debug_assertions)]
pub struct PathAnalyzer;

#[cfg(debug_assertions)]
impl PathAnalyzer {
    /// Analyze path structure for debugging
    pub fn analyze(path: &str) -> PathAnalysis {
        let params = PathResolver::extract_parameters(path);
        let content_type = ContentPathUtils::extract_content_type(path);
        let language = ContentPathUtils::extract_language(path);

        PathAnalysis {
            original_path: path.to_string(),
            extracted_params: params,
            content_type,
            language,
            is_valid: PathResolver::validate_parameters(&PathResolver::extract_parameters(path)),
        }
    }
}

#[cfg(debug_assertions)]
#[derive(Debug)]
pub struct PathAnalysis {
    pub original_path: String,
    pub extracted_params: ExtractedParams,
    pub content_type: Option<String>,
    pub language: Option<String>,
    pub is_valid: bool,
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_parameter_extraction() {
        let params = PathResolver::extract_parameters("/blog/rust/my-article");
        assert_eq!(params.slug, Some("my-article".to_string()));
        assert_eq!(params.category, Some("rust".to_string()));
    }

    #[test]
    fn test_slug_only_extraction() {
        let params = PathResolver::extract_parameters("/blog/my-article");
        assert_eq!(params.slug, Some("my-article".to_string()));
        assert_eq!(params.category, None);
    }

    #[test]
    fn test_html_path_building() {
        let path = ContentPathUtils::build_html_path("blog", "en", Some("rust"), "my-article");
        assert_eq!(path, "/blog/en/rust/my-article.html");
    }

    #[test]
    fn test_validation() {
        let valid_params = ExtractedParams {
            slug: Some("my-article".to_string()),
            category: Some("rust".to_string()),
        };
        assert!(PathResolver::validate_parameters(&valid_params));

        let invalid_params = ExtractedParams {
            slug: Some("123".to_string()),
            category: None,
        };
        assert!(!PathResolver::validate_parameters(&invalid_params));
    }
}
