//! Component match arm generation for SSR and Client rendering

use std::collections::HashMap;
use std::io::Write;

use super::types::ComponentInfo;

/// DEPRECATED: Generate SSR rendering component macro
/// This function is deprecated in favor of trait-based ServerRouteRenderer
/// Kept for backward compatibility but should not be used in new code
#[deprecated(note = "Use trait-based ServerRouteRenderer instead of generated macros")]
pub fn generate_ssr_render_component_macro(
    file: &mut std::fs::File,
    components: &HashMap<String, ComponentInfo>,
) -> Result<(), std::io::Error> {
    writeln!(
        file,
        "/// Macro to auto-generate render_component method for SSR"
    )?;
    writeln!(
        file,
        "/// This eliminates the need to manually update match statements when adding new routes"
    )?;
    writeln!(file, "#[macro_export]")?;
    writeln!(file, "macro_rules! generate_ssr_render_component {{")?;
    writeln!(file, "    () => {{")?;
    writeln!(file, "        fn render_component(")?;
    writeln!(file, "            &self,")?;
    writeln!(file, "            component: &RouteComponent,")?;
    writeln!(file, "            path: &str,")?;
    writeln!(file, "            language: &str,")?;
    writeln!(
        file,
        "            parameters: &std::collections::HashMap<String, String>,"
    )?;
    writeln!(file, "        ) -> Self::View {{")?;
    writeln!(
        file,
        "            // Import pages crate for component access"
    )?;
    writeln!(file, "            use rustelo_pages_leptos::*;")?;
    writeln!(file)?;
    writeln!(
        file,
        "            // Translations are initialized lazily on first use"
    )?;
    writeln!(file, "            let lang = language.to_string();")?;
    writeln!(file)?;
    writeln!(
        file,
        "            // Utility functions for parameter extraction"
    )?;
    generate_extraction_functions(file, true)?;
    writeln!(file)?;
    writeln!(file, "            match component {{")?;

    for (component_name, info) in components {
        generate_component_match_arm(file, component_name, info, true)?;
    }

    writeln!(file, "            }}")?;
    writeln!(file, "        }}")?;
    writeln!(file, "    }};")?;
    writeln!(file, "}}")?;
    writeln!(file)?;

    Ok(())
}

/// DEPRECATED: Generate client rendering component macro
/// This function is deprecated in favor of trait-based ClientRouteRenderer
/// Kept for backward compatibility but should not be used in new code
#[deprecated(note = "Use trait-based ClientRouteRenderer instead of generated macros")]
pub fn generate_client_render_component_macro(
    file: &mut std::fs::File,
    components: &HashMap<String, ComponentInfo>,
) -> Result<(), std::io::Error> {
    writeln!(
        file,
        "/// Macro to auto-generate render_component method for Client"
    )?;
    writeln!(
        file,
        "/// This eliminates the need to manually update match statements when adding new routes"
    )?;
    writeln!(file, "#[macro_export]")?;
    writeln!(file, "macro_rules! generate_client_render_component {{")?;
    writeln!(file, "    () => {{")?;
    writeln!(file, "        fn render_component(")?;
    writeln!(file, "            &self,")?;
    writeln!(file, "            component: &RouteComponent,")?;
    writeln!(file, "            path: &str,")?;
    writeln!(file, "            language: &str,")?;
    writeln!(
        file,
        "            parameters: &std::collections::HashMap<String, String>,"
    )?;
    writeln!(file, "        ) -> Self::View {{")?;
    writeln!(
        file,
        "            // Import pages crate for component access"
    )?;
    writeln!(file, "            use rustelo_pages_leptos::*;")?;
    writeln!(file)?;
    writeln!(file, "            let lang = language.to_string();")?;
    writeln!(file)?;
    writeln!(
        file,
        "            // Utility functions for parameter extraction"
    )?;
    generate_extraction_functions(file, false)?;
    writeln!(file)?;
    writeln!(file, "            match component {{")?;

    for (component_name, info) in components {
        generate_component_match_arm(file, component_name, info, false)?;
    }

    writeln!(file, "            }}")?;
    writeln!(file, "        }}")?;
    writeln!(file, "    }};")?;
    writeln!(file, "}}")?;

    Ok(())
}

/// Generate parameter extraction helper functions inline
fn generate_extraction_functions(
    file: &mut std::fs::File,
    _is_ssr: bool,
) -> Result<(), std::io::Error> {
    writeln!(
        file,
        "            fn extract_slug_from_path(path: &str) -> Option<String> {{"
    )?;
    writeln!(
        file,
        r#"                let path = path.strip_suffix(".html").unwrap_or(path);"#
    )?;
    writeln!(
        file,
        "                let path = path.trim_start_matches('/');"
    )?;
    writeln!(
        file,
        "                let parts: Vec<&str> = path.split('/').filter(|p| \
         !p.is_empty()).collect();"
    )?;
    writeln!(file)?;
    writeln!(file, "                if parts.len() >= 2 {{")?;
    writeln!(file, "                    let last_part = parts.last()?;")?;
    writeln!(
        file,
        "                    if last_part.chars().all(|c| c.is_ascii_digit()) {{"
    )?;
    writeln!(file, "                        return None;")?;
    writeln!(file, "                    }}")?;
    writeln!(file, "                    Some(last_part.to_string())")?;
    writeln!(file, "                }} else {{")?;
    writeln!(file, "                    None")?;
    writeln!(file, "                }}")?;
    writeln!(file, "            }}")?;
    writeln!(file)?;
    writeln!(
        file,
        "            fn extract_category_from_path(path: &str) -> Option<String> {{"
    )?;
    writeln!(
        file,
        r#"                let path = path.strip_suffix(".html").unwrap_or(path);"#
    )?;
    writeln!(
        file,
        "                let path = path.trim_start_matches('/');"
    )?;
    writeln!(
        file,
        "                let parts: Vec<&str> = path.split('/').filter(|p| \
         !p.is_empty()).collect();"
    )?;
    writeln!(file)?;
    writeln!(file, "                if parts.len() >= 2 {{")?;
    writeln!(
        file,
        "                    let category_part = parts[parts.len() - 1];"
    )?;
    writeln!(
        file,
        "                    if category_part.chars().all(|c| c.is_ascii_digit()) {{"
    )?;
    writeln!(file, "                        return None;")?;
    writeln!(file, "                    }}")?;
    writeln!(file, "                    Some(category_part.to_string())")?;
    writeln!(file, "                }} else {{")?;
    writeln!(file, "                    None")?;
    writeln!(file, "                }}")?;
    writeln!(file, "            }}")?;

    Ok(())
}

/// Generate a match arm for a specific component - fully route-agnostic
pub fn generate_component_match_arm(
    file: &mut std::fs::File,
    component_name: &str,
    info: &ComponentInfo,
    is_ssr: bool,
) -> Result<(), std::io::Error> {
    let ssr_prefix = if is_ssr { "SSR " } else { "Client " };

    writeln!(
        file,
        "                RouteComponent::{} => {{",
        component_name
    )?;

    // Generate language parameter for String - lang is already a String
    let language_param = "lang.clone()";

    // Load FTL translations for the component using lang_prefixes from route config
    writeln!(
        file,
        "                    // Load FTL translations for component"
    )?;
    writeln!(file, "                    let translations = {{")?;
    if !info.lang_prefixes.is_empty() {
        let patterns_str = info
            .lang_prefixes
            .iter()
            .map(|p| format!("\"{}\"", p))
            .collect::<Vec<_>>()
            .join(", ");
        if is_ssr {
            writeln!(
                file,
                "                        let translator = \
                 rustelo_core_lib::i18n::SsrTranslator::new(lang.clone());"
            )?;
        } else {
            writeln!(
                file,
                "                        let translator = \
                 rustelo_core_lib::i18n::UnifiedI18n::new(&lang, \"/\");"
            )?;
        }
        writeln!(
            file,
            "                        let patterns = [{}];",
            patterns_str
        )?;
        writeln!(
            file,
            "                        \
             rustelo_core_lib::i18n::helpers::build_page_content_patterns(&translator, &patterns)"
        )?;
    } else {
        writeln!(
            file,
            "                        use std::collections::HashMap;"
        )?;
        writeln!(
            file,
            "                        HashMap::<String, String>::new() // No lang_prefixes \
             configured"
        )?;
    }
    writeln!(file, "                    }};")?;

    if let Some(page_component) = &info.page_component {
        // Handle content_type for any page component that needs it
        let mut has_content_type = false;

        // Use component_dynamic field to determine if dynamic content_type detection is
        // needed
        if info.component_dynamic {
            writeln!(file, r#"                    let content_type = {{"#)?;
            writeln!(
                file,
                r#"                        // First try to get content_type from route parameters (resolved from route config)"#
            )?;
            writeln!(
                file,
                r#"                        if let Some(ct) = parameters.get("content_type") {{"#
            )?;
            writeln!(file, r#"                            ct.clone()"#)?;
            writeln!(file, r#"                        }} else {{"#)?;
            writeln!(
                file,
                r#"                            // Fallback to route resolution system instead of path parsing"#
            )?;
            writeln!(
                file,
                r#"                            rustelo_core_lib::content_resolver::resolve_content_type_from_route(path, &lang)"#
            )?;
            writeln!(
                file,
                r#"                                .unwrap_or_else(|_| "content".to_string())"#
            )?;
            writeln!(file, r#"                        }}"#)?;
            writeln!(file, r#"                    }};"#)?;
            has_content_type = true;
            writeln!(
                file,
                r#"                    tracing::info!("🔧 {{}} {{}} using dynamic content_type from route resolution: '{{}}'", "{}", "{}", content_type);"#,
                ssr_prefix, component_name
            )?;
        } else {
            // Primary: Check content_type in props (main configuration location)
            if let Some(props_str) = &info.props {
                if let Ok(props_toml) = toml::from_str::<toml::Value>(props_str) {
                    if let Some(content_type) = props_toml.get("content_type") {
                        let content_type_str = match content_type {
                            toml::Value::String(s) => s,
                            _ => content_type.as_str().unwrap_or("unknown"),
                        };
                        writeln!(
                            file,
                            r#"                    let content_type = "{}".to_string();"#,
                            content_type_str
                        )?;
                        has_content_type = true;
                        writeln!(
                            file,
                            r#"                    tracing::info!("🔧 {{}} {{}} using content_type from props: '{{}}'", "{}", "{}", content_type);"#,
                            ssr_prefix, component_name
                        )?;
                    }
                }
            }

            // Fallback: Check content_type from Route struct (legacy support)
            if !has_content_type {
                if let Some(content_type) = &info.content_type {
                    writeln!(
                        file,
                        r#"                    let content_type = "{}".to_string();"#,
                        content_type
                    )?;
                    has_content_type = true;
                    writeln!(
                        file,
                        r#"                    tracing::info!("🔧 {{}} {{}} using content_type from route config: '{{}}'", "{}", "{}", content_type);"#,
                        ssr_prefix, component_name
                    )?;
                }
            }
        }

        // Log unified content usage
        if has_content_type && page_component.contains("UnifiedContent") {
            writeln!(
                file,
                r#"                    tracing::info!("🔧 {} {} using unified content component");"#,
                ssr_prefix, component_name
            )?;
        }

        // Handle parameter extraction
        if let Some(param_extraction_str) = &info.parameter_extraction {
            if let Ok(param_extraction_toml) = toml::from_str::<toml::Value>(param_extraction_str) {
                if param_extraction_toml.get("category").is_some() {
                    writeln!(
                        file,
                        "                    let category = \
                         parameters.get(\"category\").cloned().or_else(|| \
                         extract_category_from_path(path)).unwrap_or_else(|| \"all\".to_string());"
                    )?;
                    writeln!(
                        file,
                        r#"                    tracing::info!("🔧 {} {} category: '{{}}' for path: '{{}}'", category, path);"#,
                        ssr_prefix, component_name
                    )?;
                }

                if param_extraction_toml.get("slug").is_some() {
                    writeln!(
                        file,
                        r#"                    tracing::info!("🔧 {} {} route matched for path: '{{}}', parameters: {{:?}}", path, parameters);"#,
                        ssr_prefix, component_name
                    )?;
                    writeln!(
                        file,
                        "                    if let Some(slug) = parameters.get(\"slug\") {{"
                    )?;
                    writeln!(
                        file,
                        r#"                        tracing::info!("🔧 {} {} using parameter slug: '{{}}'", slug);"#,
                        ssr_prefix, component_name
                    )?;
                }
            }
        }

        // Use the actual component (e.g., PostViewerPage) which handles SSR/Client
        // routing internally
        let component_name = if page_component.ends_with("Page") {
            page_component.clone()
        } else {
            format!("{}Page", page_component)
        };

        // Generate the view! macro call dynamically based on available props and
        // parameters
        write!(file, "                    view! {{ <{}", component_name)?;

        // Add content_type prop if available - all components use consistent naming
        if has_content_type {
            write!(file, " content_type=content_type")?;
        }

        // Add category parameter if available
        if info.parameter_extraction.as_ref().is_some_and(|p| {
            toml::from_str::<toml::Value>(p).is_ok_and(|t| t.get("category").is_some())
        }) {
            write!(file, " category=category")?;
        }

        // Add slug parameter if available - all components use consistent naming
        if info.parameter_extraction.as_ref().is_some_and(|p| {
            toml::from_str::<toml::Value>(p).is_ok_and(|t| t.get("slug").is_some())
        }) {
            write!(file, " slug=slug.clone()")?;
        }

        // Add language parameter and FTL translations
        write!(file, " _language={}", language_param)?;

        // Only add lang_content for components that support it (not routing wrappers)
        if !component_name.ends_with("Page") || component_name.starts_with("Unified") {
            write!(file, " lang_content=translations")?;
        }
        writeln!(file, " /> }}.into_any()")?;

        // Close slug extraction block if needed
        if info.parameter_extraction.as_ref().is_some_and(|p| {
            toml::from_str::<toml::Value>(p).is_ok_and(|t| t.get("slug").is_some())
        }) {
            writeln!(file, "                    }} else {{")?;
            writeln!(
                file,
                r#"                        tracing::info!("🔧 {} {} fallback: extracting slug from path");"#,
                ssr_prefix, component_name
            )?;
            writeln!(
                file,
                "                        if let Some(slug) = extract_slug_from_path(path) {{"
            )?;
            writeln!(
                file,
                r#"                            tracing::info!("🔧 {} {} extracted slug: '{{}}'", slug);"#,
                ssr_prefix, component_name
            )?;
            write!(
                file,
                "                            view! {{ <{}",
                component_name
            )?;
            if has_content_type {
                write!(file, " content_type=content_type")?;
            }
            write!(file, " _language={} slug=slug", language_param)?;

            // Only add lang_content for components that support it (not routing wrappers)
            if !component_name.ends_with("Page") || component_name.starts_with("Unified") {
                write!(file, " lang_content=translations")?;
            }
            writeln!(file, " /> }}.into_any()")?;
            writeln!(file, "                        }} else {{")?;
            writeln!(
                file,
                r#"                            tracing::warn!("🔧 {} {} no slug found - returning NotFound");"#,
                ssr_prefix, component_name
            )?;
            if let Some(fallback) = &info.fallback_component {
                writeln!(
                    file,
                    "                            view! {{ <{} _language={} /> }}.into_any()",
                    fallback, language_param
                )?;
            } else {
                writeln!(
                    file,
                    "                            view! {{ <NotFoundPage _language={} /> \
                     }}.into_any()",
                    language_param
                )?;
            }
            writeln!(file, "                        }}")?;
            writeln!(file, "                    }}")?;
        }
    } else {
        // Fallback to NotFoundPage if no page_component specified
        writeln!(
            file,
            "                    view! {{ <NotFoundPage _language={} /> }}.into_any()",
            language_param
        )?;
    }

    writeln!(file, "                }},")?;
    Ok(())
}

/// Generate parameter extraction helper functions (standalone version)
pub fn generate_parameter_extraction_functions(
    file: &mut std::fs::File,
) -> Result<(), std::io::Error> {
    writeln!(
        file,
        "/// Extract slug from a path (e.g., \"/content-type/my-post\" -> \"my-post\")"
    )?;
    writeln!(
        file,
        "fn extract_slug_from_path(path: &str) -> Option<String> {{"
    )?;
    writeln!(
        file,
        "    let path = path.strip_suffix(\".html\").unwrap_or(path);"
    )?;
    writeln!(file, "    let path = path.trim_start_matches('/');")?;
    writeln!(
        file,
        "    let parts: Vec<&str> = path.split('/').filter(|p| !p.is_empty()).collect();"
    )?;
    writeln!(file)?;
    writeln!(file, "    // Look for slug in the last path segment")?;
    writeln!(file, "    if parts.len() >= 2 {{")?;
    writeln!(file, "        let last_part = parts.last()?;")?;
    writeln!(file, "        // Don't treat page numbers as slugs")?;
    writeln!(
        file,
        "        if last_part.chars().all(|c| c.is_ascii_digit()) {{"
    )?;
    writeln!(file, "            return None;")?;
    writeln!(file, "        }}")?;
    writeln!(file, "        Some(last_part.to_string())")?;
    writeln!(file, "    }} else {{")?;
    writeln!(file, "        None")?;
    writeln!(file, "    }}")?;
    writeln!(file, "}}")?;
    writeln!(file)?;

    writeln!(
        file,
        "/// Extract category from a path (e.g., \"/content-type/rust\" -> \"rust\")"
    )?;
    writeln!(
        file,
        "fn extract_category_from_path(path: &str) -> Option<String> {{"
    )?;
    writeln!(
        file,
        "    let path = path.strip_suffix(\".html\").unwrap_or(path);"
    )?;
    writeln!(file, "    let path = path.trim_start_matches('/');")?;
    writeln!(
        file,
        "    let parts: Vec<&str> = path.split('/').filter(|p| !p.is_empty()).collect();"
    )?;
    writeln!(file)?;
    writeln!(
        file,
        "    // Look for category in the second-to-last path segment"
    )?;
    writeln!(
        file,
        "    // Examples: content-type-based paths determined dynamically from configuration"
    )?;
    writeln!(file, "    if parts.len() >= 2 {{")?;
    writeln!(
        file,
        "        let category_part = parts[parts.len() - 1]; // Last part is the category"
    )?;
    writeln!(file, "        // Don't treat page numbers as categories")?;
    writeln!(
        file,
        "        if category_part.chars().all(|c| c.is_ascii_digit()) {{"
    )?;
    writeln!(file, "            return None;")?;
    writeln!(file, "        }}")?;
    writeln!(file, "        Some(category_part.to_string())")?;
    writeln!(file, "    }} else {{")?;
    writeln!(file, "        None")?;
    writeln!(file, "    }}")?;
    writeln!(file, "}}")?;
    writeln!(file)?;

    Ok(())
}
