//! Page template system for auto-generating page components
//!
//! This module provides a template system that can automatically generate
//! complete page implementations (unified, client, SSR) from configurable
//! templates. Templates support parameter substitution and can be selected
//! based on page type.

use std::collections::HashMap;
use std::fs;
use std::path::Path;

use serde::{Deserialize, Serialize};

/// Configuration for template parameters from routes.toml
#[derive(Debug, Clone, Deserialize, Serialize, Default)]
pub struct TemplateParams {
    pub default_content_type: Option<String>,
    pub form_action: Option<String>,
    pub has_sidebar: Option<bool>,
    pub max_items: Option<u32>,
    pub show_pagination: Option<bool>,
}

/// A complete page template with all component implementations
#[derive(Debug, Clone)]
#[allow(dead_code)] // Template system fields used for future extensibility
pub struct PageTemplate {
    pub name: String,
    pub description: String,
    pub unified_template: String,
    pub client_template: String,
    pub ssr_template: String,
    pub mod_template: String,
    pub required_patterns: Vec<String>,
    pub optional_patterns: Vec<String>,
}

/// Generated page files ready to be written
#[derive(Debug)]
pub struct GeneratedPage {
    pub component_name: String,
    pub module_name: String,
    pub mod_rs: String,
    pub unified_rs: String,
    pub client_rs: String,
    pub ssr_rs: String,
}

/// Template processing context with all substitution variables
#[derive(Debug, Clone)]
pub struct TemplateContext {
    pub component_name: String,
    pub module_name: String,
    pub prefix: String,
    pub patterns: Vec<String>,
    pub params: TemplateParams,
}

impl TemplateContext {
    pub fn new(component_name: &str, i18n_patterns: &[String], params: &TemplateParams) -> Self {
        let module_name = component_name.to_lowercase();
        // Extract prefix from first pattern (remove trailing dash)
        let prefix = i18n_patterns
            .first()
            .map(|p| p.trim_end_matches('-').to_string())
            .unwrap_or_else(|| module_name.clone());

        Self {
            component_name: component_name.to_string(),
            module_name,
            prefix,
            patterns: i18n_patterns.to_vec(),
            params: params.clone(),
        }
    }

    /// Get all variables available for template substitution
    pub fn get_variables(&self) -> HashMap<String, String> {
        let mut vars = HashMap::new();

        // Basic component information
        vars.insert("ComponentName".to_string(), self.component_name.clone());
        vars.insert("ModuleName".to_string(), self.module_name.clone());
        vars.insert("prefix".to_string(), self.prefix.clone());

        // Pattern information
        vars.insert(
            "patterns".to_string(),
            format_patterns_for_rust(&self.patterns),
        );
        vars.insert(
            "primary_pattern".to_string(),
            self.patterns
                .first()
                .unwrap_or(&"content-".to_string())
                .clone(),
        );

        // Template parameters
        if let Some(content_type) = &self.params.default_content_type {
            vars.insert("default_content_type".to_string(), content_type.clone());
        }
        if let Some(form_action) = &self.params.form_action {
            vars.insert("form_action".to_string(), form_action.clone());
        }
        vars.insert(
            "has_sidebar".to_string(),
            self.params.has_sidebar.unwrap_or(false).to_string(),
        );
        vars.insert(
            "max_items".to_string(),
            self.params.max_items.unwrap_or(12).to_string(),
        );
        vars.insert(
            "show_pagination".to_string(),
            self.params.show_pagination.unwrap_or(true).to_string(),
        );

        vars
    }
}

/// Load all available page templates from embedded strings
pub fn load_templates() -> HashMap<String, PageTemplate> {
    let mut templates = HashMap::new();

    // Basic page template for simple informational pages
    templates.insert("basic_page".to_string(), create_basic_page_template());

    // Hero page template for landing pages
    templates.insert("hero_page".to_string(), create_hero_page_template());

    // Form page template for contact/request pages
    templates.insert("form_page".to_string(), create_form_page_template());

    // Content list template for blog/portfolio pages
    templates.insert("content_list".to_string(), create_content_list_template());

    templates
}

/// Generate a complete page implementation from template and context
pub fn generate_page_from_template(
    template: &PageTemplate,
    context: &TemplateContext,
) -> Result<GeneratedPage, String> {
    let variables = context.get_variables();

    let generated = GeneratedPage {
        component_name: context.component_name.clone(),
        module_name: context.module_name.clone(),
        mod_rs: substitute_template(&template.mod_template, &variables)?,
        unified_rs: substitute_template(&template.unified_template, &variables)?,
        client_rs: substitute_template(&template.client_template, &variables)?,
        ssr_rs: substitute_template(&template.ssr_template, &variables)?,
    };

    Ok(generated)
}

/// Write generated page files to the filesystem
pub fn write_generated_page(
    generated: &GeneratedPage,
    output_dir: &str,
) -> Result<(), std::io::Error> {
    let page_dir = Path::new(output_dir)
        .join("pages")
        .join("generated")
        .join(&generated.module_name);

    // Create directory structure
    fs::create_dir_all(&page_dir)?;

    // Write all component files
    fs::write(page_dir.join("mod.rs"), &generated.mod_rs)?;
    fs::write(page_dir.join("unified.rs"), &generated.unified_rs)?;
    fs::write(page_dir.join("client.rs"), &generated.client_rs)?;
    fs::write(page_dir.join("ssr.rs"), &generated.ssr_rs)?;

    println!(
        "cargo:warning=Generated page component: {}",
        generated.component_name
    );
    Ok(())
}

/// Substitute template variables with actual values
fn substitute_template(
    template: &str,
    variables: &HashMap<String, String>,
) -> Result<String, String> {
    let mut result = template.to_string();

    for (key, value) in variables {
        let placeholder = format!("{{{}}}", key);
        result = result.replace(&placeholder, value);
    }

    // Check for unsubstituted variables (basic validation)
    if result.contains('{') && result.contains('}') {
        let remaining: Vec<&str> = result.matches('{').collect::<Vec<_>>();
        if !remaining.is_empty() {
            println!(
                "cargo:warning=Template may have unsubstituted variables in: {}",
                result
            );
        }
    }

    Ok(result)
}

/// Format pattern list for Rust array syntax
fn format_patterns_for_rust(patterns: &[String]) -> String {
    let quoted_patterns: Vec<String> = patterns.iter().map(|p| format!("\"{}\"", p)).collect();
    format!("&[{}]", quoted_patterns.join(", "))
}

// Template creators for different page types
fn create_basic_page_template() -> PageTemplate {
    PageTemplate {
        name: "basic_page".to_string(),
        description: "Simple informational page with title and content".to_string(),
        unified_template: include_str!("templates/basic_page_unified.rs").to_string(),
        client_template: include_str!("templates/standard_client.rs").to_string(),
        ssr_template: include_str!("templates/standard_ssr.rs").to_string(),
        mod_template: include_str!("templates/standard_mod.rs").to_string(),
        required_patterns: vec![
            "{prefix}-page-title".to_string(),
            "{prefix}-page-content".to_string(),
        ],
        optional_patterns: vec!["{prefix}-page-description".to_string()],
    }
}

fn create_hero_page_template() -> PageTemplate {
    PageTemplate {
        name: "hero_page".to_string(),
        description: "Landing page with hero section and features".to_string(),
        unified_template: include_str!("templates/hero_page_unified.rs").to_string(),
        client_template: include_str!("templates/standard_client.rs").to_string(),
        ssr_template: include_str!("templates/standard_ssr.rs").to_string(),
        mod_template: include_str!("templates/standard_mod.rs").to_string(),
        required_patterns: vec![
            "{prefix}-hero-title".to_string(),
            "{prefix}-hero-subtitle".to_string(),
            "{prefix}-cta-primary-text".to_string(),
            "{prefix}-cta-primary-url".to_string(),
        ],
        optional_patterns: vec!["{prefix}-features-title".to_string()],
    }
}

fn create_form_page_template() -> PageTemplate {
    PageTemplate {
        name: "form_page".to_string(),
        description: "Page with contact/request form".to_string(),
        unified_template: include_str!("templates/form_page_unified.rs").to_string(),
        client_template: include_str!("templates/standard_client.rs").to_string(),
        ssr_template: include_str!("templates/standard_ssr.rs").to_string(),
        mod_template: include_str!("templates/standard_mod.rs").to_string(),
        required_patterns: vec![
            "{prefix}-page-title".to_string(),
            "{prefix}-form-description".to_string(),
        ],
        optional_patterns: vec!["{prefix}-success-message".to_string()],
    }
}

fn create_content_list_template() -> PageTemplate {
    PageTemplate {
        name: "content_list".to_string(),
        description: "List page for blog posts, portfolio items, etc.".to_string(),
        unified_template: include_str!("templates/content_list_unified.rs").to_string(),
        client_template: include_str!("templates/standard_client.rs").to_string(),
        ssr_template: include_str!("templates/standard_ssr.rs").to_string(),
        mod_template: include_str!("templates/standard_mod.rs").to_string(),
        required_patterns: vec!["{prefix}-page-title".to_string()],
        optional_patterns: vec![
            "{prefix}-page-description".to_string(),
            "{prefix}-no-items-message".to_string(),
        ],
    }
}
