//! Example demonstrating complete LLM execution pipeline
//!
//! This example shows how to:
//! 1. Parse an MDX agent file
//! 2. Transpile to Nickel
//! 3. Evaluate to AgentDefinition
//! 4. Execute with real LLM (Claude)
//!
//! Requirements:
//! - Set ANTHROPIC_API_KEY environment variable
//!
//! Run with:
//! ```bash
//! export ANTHROPIC_API_KEY=your-api-key
//! cargo run --example llm_execution
//! ```

use std::collections::HashMap;
use typedialog_ag_core::executor::AgentExecutor;
use typedialog_ag_core::nickel::NickelEvaluator;
use typedialog_ag_core::parser::MarkupParser;
use typedialog_ag_core::transpiler::NickelTranspiler;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    println!("=== TypeAgent LLM Execution Example ===\n");

    // Define a simple agent in MDX format
    let mdx_content = r#"---
@agent {
  role: creative writer,
  llm: claude-3-5-haiku-20241022
}
---

Write a haiku about {{ topic }}. Return only the haiku, nothing else.
"#;

    println!("1. Parsing MDX agent definition...");
    let parser = MarkupParser::new();
    let ast = parser.parse(mdx_content)?;
    println!("   ✓ Parsed {} AST nodes\n", ast.nodes.len());

    println!("2. Transpiling to Nickel...");
    let transpiler = NickelTranspiler::new();
    let nickel_code = transpiler.transpile(&ast)?;
    println!("   ✓ Generated Nickel code:\n");
    println!("{}\n", nickel_code);

    println!("3. Evaluating Nickel to AgentDefinition...");
    let evaluator = NickelEvaluator::new();
    let mut agent_def = evaluator.evaluate(&nickel_code)?;

    // Configure for production
    agent_def.config.max_tokens = 150;
    agent_def.config.temperature = 0.8;

    println!("   ✓ Agent configured:");
    println!("     - Role: {}", agent_def.config.role);
    println!("     - Model: {}", agent_def.config.llm);
    println!("     - Max tokens: {}", agent_def.config.max_tokens);
    println!("     - Temperature: {}\n", agent_def.config.temperature);

    println!("4. Executing agent with LLM...");
    let executor = AgentExecutor::new();

    // Provide input
    let mut inputs = HashMap::new();
    inputs.insert(
        "topic".to_string(),
        serde_json::json!("programming in Rust"),
    );

    // Execute (calls Claude API)
    println!("   → Calling Claude API...");
    let result = executor.execute(&agent_def, inputs).await?;

    println!("\n=== RESULT ===\n");
    println!("{}\n", result.output);

    println!("=== METADATA ===");
    println!("Duration: {}ms", result.metadata.duration_ms.unwrap_or(0));
    println!("Tokens used: {}", result.metadata.tokens.unwrap_or(0));
    println!(
        "Model: {}",
        result
            .metadata
            .model
            .as_ref()
            .unwrap_or(&"unknown".to_string())
    );

    if result.validation_passed {
        println!("Validation: ✓ PASSED");
    } else {
        println!("Validation: ✗ FAILED");
        for error in &result.validation_errors {
            println!("  - {}", error);
        }
    }

    println!("\n✓ Example completed successfully!");

    Ok(())
}
