//! Node code generation templates

use crate::utils::to_pascal_case;

/// Generate planner node template
pub fn planner_node(name: &str) -> String {
    format!(
        r#"//! {} - Task Planner Node
//!
//! Auto-generated node template.

use anyhow::Result;
use mecha10_core::prelude::*;
use tracing::info;

struct {} {{
    ctx: NodeContext,
}}

impl {} {{
    pub fn new(ctx: NodeContext) -> Self {{
        Self {{ ctx }}
    }}
}}

#[async_trait::async_trait]
impl Node for {} {{
    async fn initialize(&mut self) -> Result<()> {{
        info!("Initializing {} planner");
        // TODO: Initialize planning system
        Ok(())
    }}

    async fn execute(&mut self) -> Result<()> {{
        // TODO: Plan tasks
        // TODO: Publish plans
        Ok(())
    }}

    async fn shutdown(&mut self) -> Result<()> {{
        info!("Shutting down {} planner");
        Ok(())
    }}
}}

#[tokio::main]
async fn main() -> Result<()> {{
    let ctx = NodeContext::new("{}")?;
    let mut node = {}::new(ctx);

    node.initialize().await?;

    // Run node loop
    loop {{
        node.execute().await?;
        tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
    }}
}}
"#,
        name,
        to_pascal_case(name),
        to_pascal_case(name),
        to_pascal_case(name),
        name,
        name,
        name,
        to_pascal_case(name)
    )
}

/// Generate controller node template
pub fn controller_node(name: &str) -> String {
    format!(
        r#"//! {} - Controller Node
//!
//! Auto-generated node template.

use anyhow::Result;
use mecha10_core::prelude::*;
use tracing::info;

struct {} {{
    ctx: NodeContext,
}}

impl {} {{
    pub fn new(ctx: NodeContext) -> Self {{
        Self {{ ctx }}
    }}
}}

#[async_trait::async_trait]
impl Node for {} {{
    async fn initialize(&mut self) -> Result<()> {{
        info!("Initializing {} controller");
        // TODO: Initialize controller
        Ok(())
    }}

    async fn execute(&mut self) -> Result<()> {{
        // TODO: Read state
        // TODO: Compute control
        // TODO: Send commands
        Ok(())
    }}

    async fn shutdown(&mut self) -> Result<()> {{
        info!("Shutting down {} controller");
        Ok(())
    }}
}}

#[tokio::main]
async fn main() -> Result<()> {{
    let ctx = NodeContext::new("{}")?;
    let mut node = {}::new(ctx);

    node.initialize().await?;

    // Run control loop
    loop {{
        node.execute().await?;
        tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
    }}
}}
"#,
        name,
        to_pascal_case(name),
        to_pascal_case(name),
        to_pascal_case(name),
        name,
        name,
        name,
        to_pascal_case(name)
    )
}

/// Generate perception node template
pub fn perception_node(name: &str) -> String {
    format!(
        r#"//! {} - Perception Node
//!
//! Auto-generated node template.

use anyhow::Result;
use mecha10_core::prelude::*;
use tracing::info;

struct {} {{
    ctx: NodeContext,
}}

impl {} {{
    pub fn new(ctx: NodeContext) -> Self {{
        Self {{ ctx }}
    }}
}}

#[async_trait::async_trait]
impl Node for {} {{
    async fn initialize(&mut self) -> Result<()> {{
        info!("Initializing {} perception");
        // TODO: Load perception models
        Ok(())
    }}

    async fn execute(&mut self) -> Result<()> {{
        // TODO: Read sensor data
        // TODO: Run perception
        // TODO: Publish detections
        Ok(())
    }}

    async fn shutdown(&mut self) -> Result<()> {{
        info!("Shutting down {} perception");
        Ok(())
    }}
}}

#[tokio::main]
async fn main() -> Result<()> {{
    let ctx = NodeContext::new("{}")?;
    let mut node = {}::new(ctx);

    node.initialize().await?;

    // Run perception loop
    loop {{
        node.execute().await?;
        tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
    }}
}}
"#,
        name,
        to_pascal_case(name),
        to_pascal_case(name),
        to_pascal_case(name),
        name,
        name,
        name,
        to_pascal_case(name)
    )
}

/// Generate ML inference node template
pub fn ml_node(name: &str) -> String {
    format!(
        r#"//! {} - ML Inference Node
//!
//! Auto-generated node template.

use anyhow::Result;
use mecha10_core::prelude::*;
use tracing::info;

struct {} {{
    ctx: NodeContext,
}}

impl {} {{
    pub fn new(ctx: NodeContext) -> Self {{
        Self {{ ctx }}
    }}
}}

#[async_trait::async_trait]
impl Node for {} {{
    async fn initialize(&mut self) -> Result<()> {{
        info!("Initializing {} ML node");
        // TODO: Load ML model
        Ok(())
    }}

    async fn execute(&mut self) -> Result<()> {{
        // TODO: Read input data
        // TODO: Run inference
        // TODO: Publish predictions
        Ok(())
    }}

    async fn shutdown(&mut self) -> Result<()> {{
        info!("Shutting down {} ML node");
        Ok(())
    }}
}}

#[tokio::main]
async fn main() -> Result<()> {{
    let ctx = NodeContext::new("{}")?;
    let mut node = {}::new(ctx);

    node.initialize().await?;

    // Run inference loop
    loop {{
        node.execute().await?;
        tokio::time::sleep(tokio::time::Duration::from_millis(50)).await;
    }}
}}
"#,
        name,
        to_pascal_case(name),
        to_pascal_case(name),
        to_pascal_case(name),
        name,
        name,
        name,
        to_pascal_case(name)
    )
}
