//! Main route component generation functionality

// Note: Code generation removed - using pure trait-based implementations
// use super::component_generator::{
//     generate_client_render_component_macro,
// generate_parameter_extraction_functions, };
use std::collections::HashMap;
use std::fs::File;
use std::io::Write;
use std::path::Path;

use super::loader::load_routes_config;
use super::types::ComponentInfo;
use super::validation::validate_route_patterns;
use crate::utils::RouteMetadataAccess;

/// Generate route component definitions from routes.toml or
/// SITE_CONFIG_PATH/routes/ directory
pub fn generate_route_components(content_root: &str, out_dir: &str) -> Result<(), String> {
    let output_path = Path::new(out_dir).join("generated_routes.rs");

    // Try to load routes from SITE_CONFIG_PATH/routes/ directory first, then
    // fallback to routes.toml
    let routes_config = load_routes_config(content_root)?;

    println!(
        "Successfully loaded routes with {} total routes",
        routes_config.routes.len()
    );

    // Validate routes for conflicts at build time
    validate_route_patterns(&routes_config.routes)?;

    // Collect unique components with their metadata
    let mut components: HashMap<String, ComponentInfo> = HashMap::new();
    for route in &routes_config.routes {
        if route.get_enabled() {
            let component_name = route.component.clone();

            // Extract key prefix from title_key (e.g., "home-page-title" -> "home-page")
            let title_key = route.get_title_key().unwrap_or_default();
            let key_prefix = title_key
                .strip_suffix("-title")
                .unwrap_or(&format!("{}-page", component_name.to_lowercase()))
                .to_string();

            let info = ComponentInfo {
                name: component_name.clone(),
                key_prefix,
                page_component: route.get_metadata("page_component"),
                unified_component: RouteMetadataAccess::get_unified_component(route),
                lang_prefixes: route
                    .get_metadata("lang_prefixes")
                    .unwrap_or_default()
                    .split(',')
                    .map(|s| s.trim().to_string())
                    .filter(|s| !s.is_empty())
                    .collect(),
                params_component: route.get_metadata("params_component"),
                props: route.get_metadata("props"),
                parameter_extraction: route.get_metadata("parameter_extraction"),
                fallback_component: route.get_metadata("fallback_component"),
                content_type: route.content_type.clone(),

                // GENERIC COMPONENT CONFIGURATION FIELDS
                component_dynamic: route
                    .get_metadata("component_dynamic")
                    .map(|s| s.parse().unwrap_or(false))
                    .unwrap_or(false),
                component_path: route.get_metadata("component_path").unwrap_or_default(),
                component_prefix: route.get_metadata("component_prefix").unwrap_or_default(),
            };

            // Handle component merging for multiple routes using the same component
            if let Some(existing_info) = components.get(&component_name) {
                // If any route using this component has component_dynamic = true, use dynamic
                // mode
                let merged_component_dynamic =
                    existing_info.component_dynamic || info.component_dynamic;
                let mut merged_info = info.clone();
                merged_info.component_dynamic = merged_component_dynamic;

                // If using dynamic mode, clear hardcoded props to prevent conflicts
                if merged_component_dynamic {
                    merged_info.props = None;
                    merged_info.content_type = None;
                }

                components.insert(component_name, merged_info);
            } else {
                components.insert(component_name, info);
            }
        }
    }

    if components.is_empty() {
        eprintln!("Warning: No enabled components found in routes.toml");
        return generate_fallback_route_components(&output_path);
    }

    // Generate the route components file
    let mut file = File::create(&output_path)
        .map_err(|e| format!("Failed to create generated_routes.rs: {e}"))?;

    write_route_components_file(&mut file, &components)
        .map_err(|e| format!("Failed to write route components: {e}"))?;

    println!(
        "Generated route components from routes.toml with {} unique components",
        components.len()
    );
    Ok(())
}

/// Generate fallback route components when routes.toml parsing fails
fn generate_fallback_route_components(_output_path: &Path) -> Result<(), String> {
    // No hardcoded/literal route components - fail gracefully when routes can't be
    // loaded
    Err(
        "No route configurations found. Please ensure SITE_CONFIG_PATH/routes directory contains \
         valid TOML files."
            .to_string(),
    )
}

/// Write the route components file content
fn write_route_components_file(
    file: &mut File,
    components: &HashMap<String, ComponentInfo>,
) -> Result<(), std::io::Error> {
    // Generate imports
    writeln!(file, "// Auto-generated route component definitions")?;
    writeln!(
        file,
        "// This file is regenerated at build time from SITE_CONFIG_PATH/routes"
    )?;
    writeln!(file)?;
    writeln!(file, "use serde::{{Deserialize, Serialize}};")?;
    writeln!(file)?;

    // Generate RouteComponent enum with derives
    writeln!(file, "/// Enum representing different page components")?;
    writeln!(file, "/// Auto-generated from routes.toml configuration")?;
    writeln!(
        file,
        "#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]"
    )?;
    writeln!(file, "pub enum RouteComponent {{")?;

    for component_name in components.keys() {
        writeln!(file, "    {},", component_name)?;
    }

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

    // Generate RouteComponent implementation with all methods
    writeln!(file, "impl RouteComponent {{")?;

    // from_str method
    writeln!(
        file,
        "    /// Convert string component name to RouteComponent enum"
    )?;
    writeln!(file, "    pub fn from_str(component: &str) -> Self {{")?;
    writeln!(file, "        match component {{")?;
    for component_name in components.keys() {
        writeln!(
            file,
            "            \"{}\" => RouteComponent::{},",
            component_name, component_name
        )?;
    }
    writeln!(file, "            _ => RouteComponent::NotFound,")?;
    writeln!(file, "        }}")?;
    writeln!(file, "    }}")?;
    writeln!(file)?;

    // as_str method
    writeln!(
        file,
        "    /// Convert RouteComponent to string representation"
    )?;
    writeln!(file, "    pub fn as_str(&self) -> &'static str {{")?;
    writeln!(file, "        match self {{")?;
    for component_name in components.keys() {
        writeln!(
            file,
            "            RouteComponent::{} => \"{}\",",
            component_name, component_name
        )?;
    }
    writeln!(file, "        }}")?;
    writeln!(file, "    }}")?;
    writeln!(file)?;

    // title_key method
    writeln!(file, "    /// Get the default title key for i18n")?;
    writeln!(file, "    pub fn title_key(&self) -> &'static str {{")?;
    writeln!(file, "        match self {{")?;
    for (component_name, info) in components {
        writeln!(
            file,
            "            RouteComponent::{} => \"{}-title\",",
            component_name, info.key_prefix
        )?;
    }
    writeln!(file, "        }}")?;
    writeln!(file, "    }}")?;
    writeln!(file)?;

    // description_key method
    writeln!(file, "    /// Get the default description key for i18n")?;
    writeln!(file, "    pub fn description_key(&self) -> &'static str {{")?;
    writeln!(file, "        match self {{")?;
    for (component_name, info) in components {
        writeln!(
            file,
            "            RouteComponent::{} => \"{}-description\",",
            component_name, info.key_prefix
        )?;
    }
    writeln!(file, "        }}")?;
    writeln!(file, "    }}")?;
    writeln!(file)?;

    // keywords_key method
    writeln!(file, "    /// Get the default keywords key for i18n")?;
    writeln!(file, "    pub fn keywords_key(&self) -> &'static str {{")?;
    writeln!(file, "        match self {{")?;
    for (component_name, info) in components {
        writeln!(
            file,
            "            RouteComponent::{} => \"{}-keywords\",",
            component_name, info.key_prefix
        )?;
    }
    writeln!(file, "        }}")?;
    writeln!(file, "    }}")?;
    writeln!(file)?;

    // is_multilingual method
    writeln!(
        file,
        "    /// Check if this component supports multiple languages"
    )?;
    writeln!(file, "    pub fn is_multilingual(&self) -> bool {{")?;
    writeln!(file, "        !matches!(self, RouteComponent::NotFound)")?;
    writeln!(file, "    }}")?;

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

    // Generate std::str::FromStr implementation for compatibility
    writeln!(file, "impl std::str::FromStr for RouteComponent {{")?;
    writeln!(file, "    type Err = String;")?;
    writeln!(
        file,
        "    fn from_str(s: &str) -> Result<Self, Self::Err> {{"
    )?;
    writeln!(file, "        let component = match s {{")?;

    // Generate the actual match arms for the trait implementation
    for (component_name, _info) in components.iter() {
        writeln!(
            file,
            "            \"{}\" => RouteComponent::{},",
            component_name, component_name
        )?;
    }

    writeln!(
        file,
        "            _ => return Err(format!(\"Unknown route component: {{}}\", s)),"
    )?;
    writeln!(file, "        }};")?;
    writeln!(file, "        Ok(component)")?;
    writeln!(file, "    }}")?;
    writeln!(file, "}}")?;
    writeln!(file)?;

    // PHASE 3.4: Legacy code generation removed - using pure trait-based
    // implementations All rendering now handled by trait-based
    // ClientRouteRenderer and ServerRouteRenderer No more macro generation
    // needed - using runtime resolution via traits
    writeln!(
        file,
        "// Trait-based rendering - no macro generation needed"
    )?;

    Ok(())
}
