// PUBLIC DOMAIN - NO LICENSE, NO WARRANTY
// Copyright 2025 TimeHexOn & foxhop & russell@unturf
// https://www.permacomputer.com

/// UncloseAI Rust Library - Usage Examples
///
/// Demonstrates how to use the UncloseAI library for:
/// - Model discovery
/// - Non-streaming chat completions
/// - Streaming chat completions
/// - Text-to-speech generation

use uncloseai::{UncloseAI, ChatMessage, ChatOptions, UncloseAIError};
use futures_util::StreamExt;
use std::fs::File;
use std::io::Write;

/// Example: Discover available models
async fn example_model_discovery() -> Result<(), Box<dyn std::error::Error>> {
    println!("=== Model Discovery Example ===\n");

    // Initialize client (auto-discovers from environment variables)
    let client = UncloseAI::new(Some(uncloseai::UncloseAIConfig {
        debug: true,
        ..Default::default()
    })).await?;

    // List discovered models
    let models = client.list_models();
    println!("\nDiscovered {} model(s):", models.len());
    for model in models {
        println!("  - {}", model.id);
        println!("    Endpoint: {}", model.endpoint);
        println!("    Max tokens: {}", model.max_tokens);
    }
    println!();

    Ok(())
}

/// Example: Non-streaming chat completion
async fn example_chat() -> Result<(), Box<dyn std::error::Error>> {
    println!("=== Non-Streaming Chat Example ===\n");

    let client = UncloseAI::new(None).await?;

    let response = client.chat(
        "auto",  // Use first available model
        vec![
            ChatMessage::system("You are a helpful AI assistant."),
            ChatMessage::user("Explain quantum computing in one sentence."),
        ],
        Some(ChatOptions {
            max_tokens: Some(100),
            ..Default::default()
        })
    ).await?;

    // Extract and print the response
    let content = &response.choices[0].message.content;
    println!("Assistant: {}\n", content);

    Ok(())
}

/// Example: Streaming chat completion
async fn example_chat_streaming() -> Result<(), Box<dyn std::error::Error>> {
    println!("=== Streaming Chat Example ===\n");

    let client = UncloseAI::new(None).await?;

    println!("User: Write a short haiku about programming.\n");
    print!("Assistant: ");

    let mut stream = client.chat_stream(
        "auto",
        vec![
            ChatMessage::system("You are a poetic AI that writes haikus."),
            ChatMessage::user("Write a short haiku about programming."),
        ],
        Some(ChatOptions {
            max_tokens: Some(100),
            ..Default::default()
        })
    ).await?;

    // Stream and print chunks
    while let Some(chunk) = stream.next().await {
        match chunk {
            Ok(chunk) => {
                if let Some(choice) = chunk.choices.first() {
                    if let Some(content) = &choice.delta.content {
                        print!("{}", content);
                        std::io::stdout().flush()?;
                    }
                }
            }
            Err(e) => {
                println!("\nError: {}", e);
                break;
            }
        }
    }

    println!("\n");

    Ok(())
}

/// Example: Streaming chat with conversation context
async fn example_chat_streaming_with_context() -> Result<(), Box<dyn std::error::Error>> {
    println!("=== Streaming Chat with Context ===\n");

    let client = UncloseAI::new(None).await?;

    // Simulated conversation
    let mut messages = vec![
        ChatMessage::system("You are a helpful coding assistant."),
        ChatMessage::user("What is Rust used for?"),
    ];

    println!("User: What is Rust used for?\n");
    print!("Assistant: ");

    // First response
    let mut full_response = String::new();
    let mut stream = client.chat_stream(
        "auto",
        messages.clone(),
        Some(ChatOptions {
            max_tokens: Some(150),
            ..Default::default()
        })
    ).await?;

    while let Some(chunk) = stream.next().await {
        if let Ok(chunk) = chunk {
            if let Some(choice) = chunk.choices.first() {
                if let Some(content) = &choice.delta.content {
                    full_response.push_str(content);
                    print!("{}", content);
                    std::io::stdout().flush()?;
                }
            }
        }
    }

    println!("\n");

    // Add assistant response to context
    messages.push(ChatMessage::assistant(full_response));
    messages.push(ChatMessage::user("Can you give me a simple example?"));

    println!("User: Can you give me a simple example?\n");
    print!("Assistant: ");

    // Second response with context
    let mut stream = client.chat_stream(
        "auto",
        messages,
        Some(ChatOptions {
            max_tokens: Some(200),
            ..Default::default()
        })
    ).await?;

    while let Some(chunk) = stream.next().await {
        if let Ok(chunk) = chunk {
            if let Some(choice) = chunk.choices.first() {
                if let Some(content) = &choice.delta.content {
                    print!("{}", content);
                    std::io::stdout().flush()?;
                }
            }
        }
    }

    println!("\n");

    Ok(())
}

/// Example: Text-to-speech generation
async fn example_tts() -> Result<(), Box<dyn std::error::Error>> {
    println!("=== Text-to-Speech Example ===\n");

    let client = UncloseAI::new(None).await?;

    // Generate speech
    let audio_data = client.tts(
        "Hello from UncloseAI Rust library! This demonstrates text to speech generation.",
        "alloy",  // Options: alloy, echo, fable, onyx, nova, shimmer
        "tts-1"
    ).await?;

    // Save to file
    let mut file = File::create("speech.mp3")?;
    file.write_all(&audio_data)?;

    println!("[OK] Speech generated: speech.mp3 ({} bytes)\n", audio_data.len());

    Ok(())
}

/// Example: Using different models for different tasks
async fn example_multiple_models() -> Result<(), Box<dyn std::error::Error>> {
    println!("=== Multiple Models Example ===\n");

    let client = UncloseAI::new(None).await?;

    let models = client.list_models();
    if models.len() < 2 {
        println!("Note: Only one model available, using it for both examples\n");
    }

    // Use first model for general chat
    println!("Using first model for general question:");
    let response1 = client.chat(
        &models[0].id,
        vec![ChatMessage::user("What is AI?")],
        Some(ChatOptions {
            max_tokens: Some(50),
            ..Default::default()
        })
    ).await?;
    println!("  {}\n", response1.choices[0].message.content);

    // Use second model (or first if only one available) for coding
    let model_idx = if models.len() > 1 { 1 } else { 0 };
    println!("Using {} model for coding question:", if model_idx == 1 { "second" } else { "first" });
    let response2 = client.chat(
        &models[model_idx].id,
        vec![
            ChatMessage::system("You are a coding expert."),
            ChatMessage::user("Write a Rust function to check if a number is prime"),
        ],
        Some(ChatOptions {
            max_tokens: Some(200),
            ..Default::default()
        })
    ).await?;
    println!("  {}\n", response2.choices[0].message.content);

    Ok(())
}

/// Example: Error handling
async fn example_error_handling() -> Result<(), Box<dyn std::error::Error>> {
    println!("=== Error Handling Example ===\n");

    let client = UncloseAI::new(None).await?;

    // Try to use non-existent model
    match client.chat(
        "non-existent-model",
        vec![ChatMessage::user("Hello")],
        None
    ).await {
        Ok(_) => println!("Unexpected success"),
        Err(e) => println!("Caught error (expected): {}\n", e),
    }

    Ok(())
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    println!("{}", "=".repeat(60));
    println!("UncloseAI Rust Library - Examples");
    println!("{}", "=".repeat(60));
    println!();

    // Run examples
    if let Err(e) = example_model_discovery().await {
        eprintln!("Model discovery failed: {}", e);
        eprintln!("\nMake sure environment variables are set:");
        eprintln!("  MODEL_ENDPOINT_1=https://your-endpoint/v1");
        eprintln!("  TTS_ENDPOINT_1=https://your-tts-endpoint/v1");
        return Err(e);
    }

    example_chat().await?;
    example_chat_streaming().await?;
    example_chat_streaming_with_context().await?;
    example_multiple_models().await?;

    if let Err(e) = example_tts().await {
        println!("[ERROR] TTS Error: {}\n", e);
    }

    example_error_handling().await?;

    println!("{}", "=".repeat(60));
    println!("All examples completed successfully!");
    println!("{}", "=".repeat(60));

    Ok(())
}
