//! Template definitions and selection logic
//!
//! Provides template metadata and helper functions for template selection.

use super::types::TemplateType;

/// A project template with metadata
#[derive(Debug, Clone)]
pub struct Template {
    /// Template type
    pub template_type: TemplateType,
    /// Node IDs to include by default
    pub default_nodes: Vec<String>,
}

impl Template {
    /// Create a new template
    pub fn new(template_type: TemplateType, default_nodes: Vec<String>) -> Self {
        Self {
            template_type,
            default_nodes,
        }
    }

    /// Get template ID
    pub fn id(&self) -> &'static str {
        self.template_type.as_str()
    }

    /// Get template name
    pub fn name(&self) -> &'static str {
        self.template_type.display_name()
    }

    /// Get template description
    pub fn description(&self) -> &'static str {
        self.template_type.description()
    }
}

/// Get all available templates
pub fn get_all_templates() -> Vec<Template> {
    vec![
        Template::new(
            TemplateType::Basic,
            vec![
                "speaker".to_string(),
                "listener".to_string(),
                "motor".to_string(),
                "imu".to_string(),
                "teleop".to_string(),
                "simulation-bridge".to_string(),
                "diagnostics-node".to_string(),
                "websocket-bridge".to_string(),
                "image-classifier".to_string(),
                "object-detector".to_string(),
                "llm-command".to_string(),
                "behavior-executor".to_string(),
            ],
        ),
        Template::new(
            TemplateType::Rover,
            vec![
                "speaker".to_string(),
                "listener".to_string(),
                "motor".to_string(),
                "imu".to_string(),
                "teleop".to_string(),
                "simulation-bridge".to_string(),
                "diagnostics-node".to_string(),
                "websocket-bridge".to_string(),
                "image-classifier".to_string(),
                "object-detector".to_string(),
                "llm-command".to_string(),
                "behavior-executor".to_string(),
            ],
        ),
        Template::new(
            TemplateType::Arm,
            vec![
                "speaker".to_string(),
                "listener".to_string(),
                "motor".to_string(),
                "imu".to_string(),
                "teleop".to_string(),
                "simulation-bridge".to_string(),
                "diagnostics-node".to_string(),
                "websocket-bridge".to_string(),
                "image-classifier".to_string(),
                "object-detector".to_string(),
                "llm-command".to_string(),
                "behavior-executor".to_string(),
            ],
        ),
        Template::new(
            TemplateType::Humanoid,
            vec![
                "speaker".to_string(),
                "listener".to_string(),
                "motor".to_string(),
                "imu".to_string(),
                "teleop".to_string(),
                "simulation-bridge".to_string(),
                "diagnostics-node".to_string(),
                "websocket-bridge".to_string(),
                "image-classifier".to_string(),
                "object-detector".to_string(),
                "llm-command".to_string(),
                "behavior-executor".to_string(),
            ],
        ),
    ]
}

/// Get a template by its ID
pub fn get_template_by_id(id: &str) -> Option<Template> {
    let template_type = TemplateType::from_str(id)?;
    get_all_templates()
        .into_iter()
        .find(|t| t.template_type == template_type)
}

/// Get a template by type
#[allow(dead_code)] // Tested, planned for future use
pub fn get_template_by_type(template_type: TemplateType) -> Template {
    get_all_templates()
        .into_iter()
        .find(|t| t.template_type == template_type)
        .expect("Template should exist for all TemplateType variants")
}
