use std::path::PathBuf;
use std::fs;
use anyhow::{Result, Context};

pub fn generate_code(
    template: String,
    output: Option<PathBuf>,
    name: Option<String>,
    force: bool,
    verbose: bool,
) -> Result<()> {
    if verbose {
        println!("🔧 Generating code:");
        println!("  Template: {}", template);
        println!(
            "  Output: {}", output.as_ref().map(| p | p.display().to_string())
            .unwrap_or_else(|| "current directory".to_string())
        );
        println!("  Name: {}", name.as_deref().unwrap_or("generated"));
    }
    let project_dir = find_project_root()?;
    let output_path = output.unwrap_or_else(|| project_dir.join("src"));
    fs::create_dir_all(&output_path).context("Failed to create output directory")?;
    match template.as_str() {
        "agent" => generate_agent_template(&output_path, name, force, verbose)?,
        "workflow" => generate_workflow_template(&output_path, name, force, verbose)?,
        "crew" => generate_crew_template(&output_path, name, force, verbose)?,
        "context" => generate_context_template(&output_path, name, force, verbose)?,
        "test" => generate_test_template(&output_path, name, force, verbose)?,
        "benchmark" => generate_benchmark_template(&output_path, name, force, verbose)?,
        _ => {
            return Err(
                anyhow::anyhow!(
                    "Unknown template '{}'. Available templates: agent, workflow, crew, context, test, benchmark",
                    template
                ),
            );
        }
    }
    println!("✅ Generated {} template successfully!", template);
    Ok(())
}
fn generate_agent_template(
    output_path: &PathBuf,
    name: Option<String>,
    force: bool,
    verbose: bool,
) -> Result<()> {
    let agent_name = name.unwrap_or_else(|| "MyAgent".to_string());
    let filename = format!("{}.hlx", agent_name.to_lowercase());
    let file_path = output_path.join(&filename);
    if file_path.exists() && !force {
        return Err(
            anyhow::anyhow!(
                "File '{}' already exists. Use --force to overwrite.", file_path
                .display()
            ),
        );
    }
    let template = format!(
        r#"// {} - AI Agent Configuration
// Generated by HELIX Compiler

agent {} {{
    name: "{}"
    description: "AI agent for {}"
    model: "gpt-4"
    temperature: 0.7
    max_tokens: 2048
    
    system_prompt: |
        You are {}, a specialized AI agent.
        Your role is to assist with {}.
        
        Guidelines:
        - Be helpful and accurate
        - Provide clear explanations
        - Ask clarifying questions when needed
    
    capabilities: [
        "reasoning"
        "analysis"
        "communication"
    ]
    
    tools: [
        // Add tool configurations here
    ]
    
    constraints: [
        "Always be truthful"
        "Respect user privacy"
        "Provide helpful responses"
    ]
    
    examples: [
        {{
            input: "Example input"
            output: "Expected output"
        }}
    ]
}}
"#,
        agent_name, agent_name, agent_name, agent_name.to_lowercase(), agent_name,
        agent_name.to_lowercase()
    );
    fs::write(&file_path, template).context("Failed to write agent template")?;
    if verbose {
        println!("  Created: {}", file_path.display());
    }
    Ok(())
}
fn generate_workflow_template(
    output_path: &PathBuf,
    name: Option<String>,
    force: bool,
    verbose: bool,
) -> Result<()> {
    let workflow_name = name.unwrap_or_else(|| "MyWorkflow".to_string());
    let filename = format!("{}.hlx", workflow_name.to_lowercase());
    let file_path = output_path.join(&filename);
    if file_path.exists() && !force {
        return Err(
            anyhow::anyhow!(
                "File '{}' already exists. Use --force to overwrite.", file_path
                .display()
            ),
        );
    }
    let template = format!(
        r#"// {} - Workflow Configuration
// Generated by HELIX Compiler

workflow {} {{
    name: "{}"
    description: "Workflow for {}"
    
    triggers: [
        {{
            type: "manual"
            description: "Manual execution"
        }}
    ]
    
    steps: [
        {{
            name: "step1"
            agent: "MyAgent"
            input: {{
                prompt: "Process the input data"
            }}
            output: "processed_data"
        }}
        {{
            name: "step2"
            agent: "MyAgent"
            input: {{
                data: "{{processed_data}}"
                prompt: "Analyze the processed data"
            }}
            output: "analysis_result"
        }}
    ]
    
    error_handling: {{
        retry_count: 3
        retry_delay: 1000
        fallback_action: "notify_admin"
    }}
    
    monitoring: {{
        enabled: true
        metrics: ["execution_time", "success_rate", "error_count"]
    }}
}}
"#,
        workflow_name, workflow_name, workflow_name, workflow_name.to_lowercase()
    );
    fs::write(&file_path, template).context("Failed to write workflow template")?;
    if verbose {
        println!("  Created: {}", file_path.display());
    }
    Ok(())
}
fn generate_crew_template(
    output_path: &PathBuf,
    name: Option<String>,
    force: bool,
    verbose: bool,
) -> Result<()> {
    let crew_name = name.unwrap_or_else(|| "MyCrew".to_string());
    let filename = format!("{}.hlx", crew_name.to_lowercase());
    let file_path = output_path.join(&filename);
    if file_path.exists() && !force {
        return Err(
            anyhow::anyhow!(
                "File '{}' already exists. Use --force to overwrite.", file_path
                .display()
            ),
        );
    }
    let template = format!(
        r#"// {} - Crew Configuration
// Generated by HELIX Compiler

crew {} {{
    name: "{}"
    description: "Crew for {}"
    
    agents: [
        {{
            name: "Agent1"
            role: "Primary Agent"
            specialization: "main_task"
        }}
        {{
            name: "Agent2"
            role: "Support Agent"
            specialization: "support_task"
        }}
    ]
    
    collaboration: {{
        mode: "sequential"
        communication: "structured"
        decision_making: "consensus"
    }}
    
    workflow: {{
        name: "MyWorkflow"
        steps: [
            "Agent1 processes input"
            "Agent2 reviews and validates"
            "Both agents collaborate on final output"
        ]
    }}
    
    performance: {{
        target_accuracy: 0.95
        max_execution_time: 30000
        quality_threshold: 0.8
    }}
}}
"#,
        crew_name, crew_name, crew_name, crew_name.to_lowercase()
    );
    fs::write(&file_path, template).context("Failed to write crew template")?;
    if verbose {
        println!("  Created: {}", file_path.display());
    }
    Ok(())
}
fn generate_context_template(
    output_path: &PathBuf,
    name: Option<String>,
    force: bool,
    verbose: bool,
) -> Result<()> {
    let context_name = name.unwrap_or_else(|| "MyContext".to_string());
    let filename = format!("{}.hlx", context_name.to_lowercase());
    let file_path = output_path.join(&filename);
    if file_path.exists() && !force {
        return Err(
            anyhow::anyhow!(
                "File '{}' already exists. Use --force to overwrite.", file_path
                .display()
            ),
        );
    }
    let template = format!(
        r#"// {} - Context Configuration
// Generated by HELIX Compiler

context {} {{
    name: "{}"
    description: "Context for {}"
    
    variables: {{
        api_key: "{{env.API_KEY}}"
        base_url: "https:
        timeout: 30000
        retry_count: 3
    }}
    
    resources: [
        {{
            name: "database"
            type: "postgresql"
            connection_string: "{{env.DATABASE_URL}}"
        }}
        {{
            name: "cache"
            type: "redis"
            connection_string: "{{env.REDIS_URL}}"
        }}
    ]
    
    environment: {{
        development: {{
            debug: true
            log_level: "debug"
        }}
        production: {{
            debug: false
            log_level: "info"
        }}
    }}
    
    security: {{
        encryption: true
        authentication: "bearer_token"
        rate_limiting: {{
            requests_per_minute: 100
            burst_limit: 200
        }}
    }}
}}
"#,
        context_name, context_name, context_name, context_name.to_lowercase()
    );
    fs::write(&file_path, template).context("Failed to write context template")?;
    if verbose {
        println!("  Created: {}", file_path.display());
    }
    Ok(())
}
fn generate_test_template(
    output_path: &PathBuf,
    name: Option<String>,
    force: bool,
    verbose: bool,
) -> Result<()> {
    let test_name = name.unwrap_or_else(|| "MyTest".to_string());
    let filename = format!("test_{}.hlx", test_name.to_lowercase());
    let file_path = output_path.join(&filename);
    if file_path.exists() && !force {
        return Err(
            anyhow::anyhow!(
                "File '{}' already exists. Use --force to overwrite.", file_path
                .display()
            ),
        );
    }
    let template = format!(
        r#"

test {} {{
    name: "{}"
    description: "Test for {}"
    
    setup: {{
        
        mock_data: true
        test_environment: "development"
    }}
    
    test_cases: [
        {{
            name: "basic_functionality"
            input: {{
                message: "Hello, world!"
            }}
            expected_output: {{
                response: "Hello, world!"
                status: "success"
            }}
        }}
        {{
            name: "error_handling"
            input: {{
                message: ""
            }}
            expected_output: {{
                error: "Invalid input"
                status: "error"
            }}
        }}
    ]
    
    assertions: [
        "response.status == 'success'"
        "response.time < 1000"
        "response.accuracy > 0.9"
    ]
    
    cleanup: {{
        
        remove_temp_files: true
        reset_state: true
    }}
}}
"#,
        test_name, test_name, test_name
    );
    fs::write(&file_path, template).context("Failed to write test template")?;
    if verbose {
        println!("  Created: {}", file_path.display());
    }
    Ok(())
}
fn generate_benchmark_template(
    output_path: &PathBuf,
    name: Option<String>,
    force: bool,
    verbose: bool,
) -> Result<()> {
    let benchmark_name = name.unwrap_or_else(|| "MyBenchmark".to_string());
    let filename = format!("bench_{}.hlx", benchmark_name.to_lowercase());
    let file_path = output_path.join(&filename);
    if file_path.exists() && !force {
        return Err(
            anyhow::anyhow!(
                "File '{}' already exists. Use --force to overwrite.", file_path
                .display()
            ),
        );
    }
    let template = format!(
        r#"

benchmark {} {{
    name: "{}"
    description: "Benchmark for {}"
    
    configuration: {{
        iterations: 1000
        warmup_iterations: 100
        timeout: 30000
        parallel: false
    }}
    
    test_data: [
        {{
            name: "small_input"
            size: "1KB"
            data: "Small test data"
        }}
        {{
            name: "medium_input"
            size: "10KB"
            data: "Medium test data with more content"
        }}
        {{
            name: "large_input"
            size: "100KB"
            data: "Large test data with extensive content"
        }}
    ]
    
    metrics: [
        "execution_time"
        "memory_usage"
        "cpu_usage"
        "throughput"
    ]
    
    thresholds: {{
        max_execution_time: 1000
        max_memory_usage: 50MB
        min_throughput: 100
    }}
    
    reporting: {{
        format: "json"
        include_details: true
        save_results: true
    }}
}}
"#,
        benchmark_name, benchmark_name, benchmark_name
    );
    fs::write(&file_path, template).context("Failed to write benchmark template")?;
    if verbose {
        println!("  Created: {}", file_path.display());
    }
    Ok(())
}
fn find_project_root() -> Result<PathBuf> {
    let mut current_dir = std::env::current_dir()
        .context("Failed to get current directory")?;
    loop {
        let manifest_path = current_dir.join("project.hlx");
        if manifest_path.exists() {
            return Ok(current_dir);
        }
        if let Some(parent) = current_dir.parent() {
            current_dir = parent.to_path_buf();
        } else {
            break;
        }
    }
    Err(anyhow::anyhow!("No HELIX project found. Run 'helix init' first."))
}