//! Route resolution logic for the routing engine
//!
//! This module contains the core logic for resolving paths to routes,
//! including parametric route matching and content type resolution.

use std::collections::HashMap;
use std::str::FromStr;

use super::content::{content_exists, content_exists_with_category};
use super::factory::{
    create_content_post_resolution, create_not_found_resolution,
    create_parametric_resolution_from_toml_route, create_resolution_from_toml_route,
};
use super::parameters::{extract_multiple_parameters, extract_parameter_from_route};
use super::types::RouteResolution;
use crate::routing::components::{RouteComponent, RoutesConfig};
use crate::routing::utils::extract_lang_and_path;

/// Resolve a path to a route with complete metadata
pub fn resolve_unified_route(toml_config: &RoutesConfig, path: &str) -> RouteResolution {
    let debug_value = crate::get_debug_value();
    if debug_value > 3 {
        #[cfg(target_arch = "wasm32")]
        web_sys::console::log_1(&format!("🔍 ROUTING: Resolving path: {}", path).into());
    }
    let (language, clean_path) = extract_lang_and_path(path);

    // Debug language detection
    #[cfg(not(target_arch = "wasm32"))]
    if debug_value > 2 {
        tracing::debug!(
            "🔍 ROUTING: Path '{}' → language='{}', clean_path='{}'",
            path,
            language,
            clean_path
        );
    }

    #[cfg(target_arch = "wasm32")]
    if debug_value > 2 {
        web_sys::console::log_1(
            &format!(
                "🔍 ROUTING: Extracted - language: {}, clean_path: {}",
                language, clean_path
            )
            .into(),
        );
    }

    // Try to find exact TOML route match
    #[cfg(not(target_arch = "wasm32"))]
    if debug_value > 3 {
        tracing::debug!(
            "🔍 ROUTING: Looking for exact route match among {} routes",
            toml_config.routes.len()
        );
    }

    for route in &toml_config.routes {
        if !route.enabled {
            continue;
        }

        #[cfg(not(target_arch = "wasm32"))]
        if debug_value > 4 {
            tracing::debug!(
                "🔍 ROUTING: Checking route '{}' (lang: {}, enabled: {}) against path '{}' (lang: \
                 {})",
                route.path,
                route.language,
                route.enabled,
                path,
                language
            );
        }

        if route.path == path || (route.path == clean_path && route.language == language) {
            if debug_value > 3 {
                #[cfg(target_arch = "wasm32")]
                web_sys::console::log_1(
                    &format!("✅ ROUTING: Found exact TOML match: {}", route.path).into(),
                );
                #[cfg(not(target_arch = "wasm32"))]
                tracing::debug!(
                    "✅ ROUTING: Found exact TOML match: {} -> {}",
                    route.path,
                    route.component
                );
            }
            return create_resolution_from_toml_route(route, path, &language);
        }
    }

    if debug_value > 3 {
        // Try to match TOML routes with parameters (like /{content_type}/{category})
        #[cfg(target_arch = "wasm32")]
        web_sys::console::log_1(&"🔍 ROUTING: Trying parametric TOML routes...".into());
        #[cfg(not(target_arch = "wasm32"))]
        tracing::debug!("🔍 ROUTING: Trying parametric TOML routes...");
    }

    if let Some(parametric_resolution) =
        resolve_parametric_toml_route(toml_config, path, &language, &clean_path)
    {
        if debug_value > 3 {
            #[cfg(target_arch = "wasm32")]
            web_sys::console::log_1(&"✅ ROUTING: Found parametric TOML match!".into());
            #[cfg(not(target_arch = "wasm32"))]
            tracing::debug!("✅ ROUTING: Found parametric TOML match!");
        }
        return parametric_resolution;
    }

    if debug_value > 3 {
        // Create not found resolution
        #[cfg(target_arch = "wasm32")]
        web_sys::console::log_1(&"❌ ROUTING: No route found, returning 404".into());
    }
    create_not_found_resolution(path, &language)
}

/// Resolve parametric TOML routes (like /{content_type}/{category})
pub fn resolve_parametric_toml_route(
    toml_config: &RoutesConfig,
    path: &str,
    language: &str,
    clean_path: &str,
) -> Option<RouteResolution> {
    #[cfg(target_arch = "wasm32")]
    web_sys::console::log_1(
        &format!(
            "🔍 ROUTING: Checking parametric routes for path: {}, clean_path: {}",
            path, clean_path
        )
        .into(),
    );

    for route in &toml_config.routes {
        if !route.enabled || route.language != language {
            continue;
        }

        // Check if route contains parameters (indicated by curly braces)
        if route.path.contains('{') && route.path.contains('}') {
            #[cfg(not(target_arch = "wasm32"))]
            tracing::debug!(
                "🔍 ROUTING: Checking parametric route pattern: {} for path: {}",
                route.path,
                clean_path
            );

            #[cfg(target_arch = "wasm32")]
            web_sys::console::log_1(
                &format!(
                    "🔍 ROUTING: Checking parametric route pattern: {}",
                    route.path
                )
                .into(),
            );

            // Try multi-parameter extraction first (for patterns like
            // /{content_type}/{category}/{slug})
            if let Some(parameters) = extract_multiple_parameters(&route.path, clean_path) {
                #[cfg(not(target_arch = "wasm32"))]
                tracing::debug!(
                    "🔍 ROUTING: Multi-parameter extraction - route: '{}', parameters: {:?}",
                    route.path,
                    parameters
                );
                #[cfg(not(target_arch = "wasm32"))]
                tracing::debug!(
                    "🔍 ROUTING: Found multi-parameter match for pattern: {} with params: {:?}",
                    route.path,
                    parameters
                );

                #[cfg(target_arch = "wasm32")]
                web_sys::console::log_1(
                    &format!(
                        "🔍 ROUTING: Found multi-parameter match for pattern: {} with {} params",
                        route.path,
                        parameters.len()
                    )
                    .into(),
                );

                // Handle multi-parameter routes (like /{content_type}/{category}/{slug})
                if let (Some(slug_param), Some(category_param)) =
                    (parameters.get("slug"), parameters.get("category"))
                {
                    // Use route's content_type if available, otherwise derive from component name.
                    // No hardcoded path prefixes — the route config is the single source of truth.
                    let content_type = route
                        .get_content_type()
                        .or_else(|| crate::get_content_type_from_component(&route.component))
                        .unwrap_or_else(|| "unknown".to_string());

                    #[cfg(target_arch = "wasm32")]
                    web_sys::console::log_1(
                        &format!(
                            "🔍 ROUTING: Multi-parameter route - component: '{}', content_type: \
                             '{}', category: '{}', slug_param: '{}'",
                            route.component, content_type, category_param, slug_param
                        )
                        .into(),
                    );

                    #[cfg(not(target_arch = "wasm32"))]
                    tracing::debug!(
                        "🔍 ROUTING: Multi-parameter route - component: '{}', content_type: '{}', \
                         category: '{}', slug_param: '{}'",
                        route.component,
                        content_type,
                        category_param,
                        slug_param
                    );

                    // Handle both .html and non-.html URLs
                    let slug = if slug_param.ends_with(".html") {
                        slug_param
                            .strip_suffix(".html")
                            .unwrap_or(slug_param.as_str())
                    } else {
                        slug_param.as_str()
                    };

                    #[cfg(target_arch = "wasm32")]
                    web_sys::console::log_1(
                        &format!(
                            "🔍 ROUTING: Checking content exists - type: '{}', slug: '{}', \
                             language: '{}', category: '{}'",
                            content_type, slug, language, category_param
                        )
                        .into(),
                    );

                    let exists = content_exists_with_category(
                        &content_type,
                        slug,
                        language,
                        Some(category_param),
                    );

                    #[cfg(target_arch = "wasm32")]
                    web_sys::console::log_1(
                        &format!(
                            "🔍 ROUTING: Content exists check result: {} for slug: '{}'",
                            exists, slug
                        )
                        .into(),
                    );

                    if exists {
                        #[cfg(not(target_arch = "wasm32"))]
                        tracing::debug!(
                            "✅ ROUTING: Matched multi-parameter {} post route: {} -> category: \
                             {}, slug: {}",
                            content_type,
                            route.path,
                            category_param,
                            slug
                        );

                        #[cfg(target_arch = "wasm32")]
                        web_sys::console::log_1(
                            &format!(
                                "✅ ROUTING: Creating RouteResolution - component: '{}', path: \
                                 '{}', language: '{}'",
                                route.component, path, language
                            )
                            .into(),
                        );

                        let route_component =
                            RouteComponent::from_str(&route.component).unwrap_or_default();

                        #[cfg(target_arch = "wasm32")]
                        web_sys::console::log_1(
                            &format!(
                                "✅ ROUTING: Route component converted: '{:?}'",
                                route_component
                            )
                            .into(),
                        );

                        let mut route_parameters = HashMap::new();
                        route_parameters.insert("category".to_string(), category_param.clone());
                        route_parameters.insert("slug".to_string(), slug.to_string());

                        return Some(RouteResolution {
                            path: path.to_string(),
                            language: language.to_string(),
                            component: Some(route_component),
                            canonical_path: clean_path.to_string(),
                            metadata: super::types::RouteMetadata {
                                title: Some(format!("{}-post-title", content_type)),
                                description: Some(format!("{}-post-description", content_type)),
                                keywords: vec![
                                    content_type.to_string(),
                                    "post".to_string(),
                                    category_param.clone(),
                                ],
                                language: language.to_string(),
                                canonical_path: clean_path.to_string(),
                            },
                            exists: true,
                            parameters: route_parameters,
                            rendering_profile:
                                rustelo_core_types::rendering::resolve_rendering_profile(
                                    route.rendering_profile,
                                ),
                            template: route.template.clone(),
                        });
                    } else {
                        #[cfg(target_arch = "wasm32")]
                        web_sys::console::log_1(
                            &format!(
                                "❌ ROUTING: Content doesn't exist - type: '{}', slug: '{}', \
                                 continuing search...",
                                content_type, slug
                            )
                            .into(),
                        );
                    }
                }

                // Handle single slug parameter (fallback for multi-parameter that didn't match
                // above)
                if let Some(slug_param) = parameters.get("slug") {
                    if slug_param.ends_with(".html") {
                        let slug = slug_param
                            .strip_suffix(".html")
                            .unwrap_or(slug_param.as_str());

                        // Use route's content_type if available, otherwise extract from route path
                        let content_type = route
                            .get_content_type()
                            .or_else(|| {
                                // Extract content type from route path (e.g.,
                                // "/blog/{category}/{slug}" -> "blog")
                                if route.path.starts_with("/blog") {
                                    Some("blog".to_string())
                                } else if route.path.starts_with("/recipes") {
                                    Some("recipes".to_string())
                                } else if route.path.starts_with("/content") {
                                    Some("content".to_string())
                                } else {
                                    crate::get_content_type_from_component(&route.component)
                                }
                            })
                            .unwrap_or_else(|| "unknown".to_string());

                        let exists = content_exists(&content_type, slug, language);

                        if exists {
                            return Some(create_content_post_resolution(
                                path,
                                language,
                                &content_type,
                                slug,
                            ));
                        }
                    }
                }

                // Handle category parameter for category listing routes
                if let Some(category_param) = parameters.get("category") {
                    // Use route's content_type if available, otherwise fall back to component
                    // mapping
                    #[cfg(not(target_arch = "wasm32"))]
                    tracing::debug!(
                        "🔍 ROUTING: Route content_type field: {:?}",
                        route.get_content_type()
                    );

                    let content_type = route
                        .get_content_type()
                        .or_else(|| {
                            #[cfg(not(target_arch = "wasm32"))]
                            tracing::debug!(
                                "🔍 ROUTING: Extracting content type from route path: {}",
                                route.path
                            );
                            // Extract content type from route path (e.g., "/blog/{category}" ->
                            // "blog")
                            if route.path.starts_with("/blog") {
                                Some("blog".to_string())
                            } else if route.path.starts_with("/recipes") {
                                Some("recipes".to_string())
                            } else if route.path.starts_with("/content") {
                                Some("content".to_string())
                            } else {
                                crate::get_content_type_from_component(&route.component)
                            }
                        })
                        .unwrap_or_else(|| "unknown".to_string());

                    #[cfg(not(target_arch = "wasm32"))]
                    tracing::debug!(
                        "🔍 ROUTING: Category validation - route.component: '{}', content_type: \
                         '{}', category_param: '{}'",
                        route.component,
                        content_type,
                        category_param
                    );

                    #[cfg(target_arch = "wasm32")]
                    web_sys::console::log_1(
                        &format!(
                            "🔍 ROUTING: Client calling is_valid_category - content_type: '{}', \
                             category: '{}'",
                            content_type, category_param
                        )
                        .into(),
                    );

                    let is_valid =
                        crate::categories::is_valid_category(&content_type, category_param);

                    #[cfg(target_arch = "wasm32")]
                    web_sys::console::log_1(
                        &format!(
                            "🔍 ROUTING: Client category validation result - content_type: '{}', \
                             category: '{}', valid: {}",
                            content_type, category_param, is_valid
                        )
                        .into(),
                    );

                    if is_valid {
                        // Create a category listing resolution
                        return Some(RouteResolution {
                            path: path.to_string(),
                            language: language.to_string(),
                            component: Some(
                                RouteComponent::from_str(&route.component).unwrap_or_default(),
                            ),
                            canonical_path: clean_path.to_string(),
                            metadata: super::types::RouteMetadata {
                                title: Some("category-page-title".to_string()),
                                description: Some("category-page-description".to_string()),
                                keywords: vec![
                                    content_type.to_string(),
                                    "category".to_string(),
                                    category_param.clone(),
                                ],
                                language: language.to_string(),
                                canonical_path: clean_path.to_string(),
                            },
                            exists: true,
                            parameters: {
                                let mut params = HashMap::new();
                                params.insert("category".to_string(), category_param.clone());
                                params
                            },
                            rendering_profile:
                                rustelo_core_types::rendering::resolve_rendering_profile(
                                    route.rendering_profile,
                                ),
                            template: route.template.clone(),
                        });
                    }
                }
            } else if let Some((parameter_name, parameter_value)) =
                extract_parameter_from_route(&route.path, clean_path)
            {
                // Fallback to single parameter extraction for backward compatibility
                #[cfg(not(target_arch = "wasm32"))]
                tracing::debug!(
                    "🔍 ROUTING: Checking single parametric route pattern: {} for {}={} in \
                     language: {}",
                    route.path,
                    parameter_name,
                    parameter_value,
                    language
                );

                #[cfg(target_arch = "wasm32")]
                web_sys::console::log_1(
                    &format!(
                        "🔍 ROUTING: Checking single parametric route pattern: {} for {}={}",
                        route.path, parameter_name, parameter_value
                    )
                    .into(),
                );

                // Use route's content_type if available, otherwise fall back to component
                // mapping
                let content_type = route
                    .get_content_type()
                    .or_else(|| crate::get_content_type_from_component(&route.component))
                    .unwrap_or_else(|| "unknown".to_string());

                if parameter_value.ends_with(".html") {
                    // Handle post routes (with .html extension)
                    let slug = parameter_value
                        .strip_suffix(".html")
                        .unwrap_or(parameter_value.as_str());

                    let exists = content_exists(&content_type, slug, language);

                    if exists {
                        #[cfg(not(target_arch = "wasm32"))]
                        tracing::debug!(
                            "✅ ROUTING: Matched {} post route: {} -> slug: {}",
                            content_type,
                            route.path,
                            slug
                        );

                        return Some(create_content_post_resolution(
                            path,
                            language,
                            &content_type,
                            slug,
                        ));
                    }
                } else {
                    // Handle routes without .html extension - try both category and post
                    // First try as category route
                    if crate::categories::is_valid_category(&content_type, &parameter_value) {
                        #[cfg(target_arch = "wasm32")]
                        web_sys::console::log_1(
                            &format!(
                                "✅ ROUTING: Matched {} category route: {} -> category: {}",
                                content_type, route.path, parameter_value
                            )
                            .into(),
                        );
                        #[cfg(not(target_arch = "wasm32"))]
                        tracing::debug!(
                            "✅ ROUTING: Matched {} category route: {} -> category: {}",
                            content_type,
                            route.path,
                            parameter_value
                        );

                        return Some(create_parametric_resolution_from_toml_route(
                            route,
                            path,
                            language,
                            Some(parameter_value),
                        ));
                    }

                    // If not a valid category, try as post slug (without .html extension)
                    let exists = content_exists(&content_type, &parameter_value, language);
                    if exists {
                        #[cfg(not(target_arch = "wasm32"))]
                        tracing::debug!(
                            "✅ ROUTING: Matched {} post route (no .html): {} -> slug: {}",
                            content_type,
                            route.path,
                            parameter_value
                        );

                        #[cfg(target_arch = "wasm32")]
                        web_sys::console::log_1(
                            &format!(
                                "✅ ROUTING: Matched {} post route (no .html): {} -> slug: {}",
                                content_type, route.path, parameter_value
                            )
                            .into(),
                        );

                        return Some(create_content_post_resolution(
                            path,
                            language,
                            &content_type,
                            &parameter_value,
                        ));
                    }
                }
            }
        }
    }

    None
}
