# SkyReels SDK for Rust

A comprehensive Rust SDK for interacting with the SkyReels AI Video Generation API.

## Features

- 🎬 **Text-to-Video Generation**: Generate videos from text prompts
- 🔄 **Async/Await**: Built on Tokio for efficient async operations
- 🛡️ **Type-Safe**: Strong typing with Rust's type system
- 🎯 **Error Handling**: Comprehensive error types with retry logic
- 🔧 **Configurable**: Support for custom base URLs and API keys
- 📝 **Well-Documented**: Extensive documentation and examples

## Environment Setup

### Using .env File (Recommended for Examples)

The examples use `dotenv` to load environment variables from a `.env` file:

1. Copy the example environment file:
   ```bash
   cp .env.example .env
   ```

2. Edit `.env` and add your API key:
   ```env
   SKYREELS_API_KEY=your_actual_api_key_here
   ```

3. Run examples (they will automatically load the .env file):
   ```bash
   cargo run --example basic_usage
   ```

### Manual Environment Variable Setup

Alternatively, you can set environment variables directly:

```bash
export SKYREELS_API_KEY="your_api_key_here"
cargo run --example basic_usage
```

## Installation

Add this to your `Cargo.toml`:

```toml
[dependencies]
skyreels-sdk = "0.1.0"
tokio = { version = "1", features = ["full"] }
```

## Quick Start

```rust
use skyreels_sdk::{AspectRatio, Mode, SkyReelsClient};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create a client with your API key
    let client = SkyReelsClient::new("your_api_key");

    // Submit a text-to-video task
    let task_id = client.text2video()
        .submit_request("A beautiful sunset over the ocean")
        .duration(5)
        .aspect_ratio(AspectRatio::Wide16x9)
        .sound(true)
        .mode(Mode::Std)
        .build();

    // Note: You need to submit the request (this is just building it)
    // In a real scenario, you would use the submit method

    // Query task status
    let status = client.text2video()
        .get_task(&task_id)
        .await?;

    println!("Task status: {}", status.get_status());

    Ok(())
}
```

## Examples

The SDK includes several examples demonstrating various features:

### Environment Test

First, test your environment setup:

```bash
cargo run --example test_env
```

This will verify that your `.env` file is properly configured.

### Basic Usage

```bash
cargo run --example basic_usage
```

Demonstrates:
- Creating a client
- Submitting text-to-video tasks
- Querying task status
- Different aspect ratios and modes

### Complete Workflow

```bash
cargo run --example complete_workflow
```

Demonstrates:
- Submitting a task
- Polling for completion
- Extracting video data
- Error handling

### Error Handling

```bash
cargo run --example error_handling
```

Demonstrates:
- Different error types
- Retry logic for retryable errors
- Status code handling
- Best practices for error handling

### Environment Setup Test

```bash
cargo run --example test_env
```

Verifies that environment variables are loaded correctly from `.env` file.

### Custom Client Configuration

```bash
cargo run --example custom_client
```

Demonstrates:
- Custom base URLs
- Dynamic API key updates
- Multiple clients for different environments
- Proxy configuration

## API Documentation

### Client Configuration

```rust
// Default client
let client = SkyReelsClient::new("your_api_key");

// Custom base URL
let client = SkyReelsClient::with_base_url(
    "your_api_key",
    "https://custom-gateway.example.com"
);

// Update API key dynamically
client.set_api_key("new_api_key").await;

// Update base URL dynamically
client.set_base_url("https://new-gateway.example.com").await;
```

### Text-to-Video Generation

```rust
use skyreels_sdk::{AspectRatio, Mode};

// Submit a task
let task_id = client.text2video()
    .submit_request("Your prompt here")
    .duration(5)           // 3-15 seconds (default: 5)
    .aspect_ratio(AspectRatio::Wide16x9)  // 16:9, 4:3, 1:1, 9:16, 3:4
    .sound(true)           // Include sound effects
    .mode(Mode::Std)       // Fast, Std, Pro
    .build();
```

### Task Status Query

```rust
let response = client.text2video()
    .get_task(&task_id)
    .await?;

match response.get_status() {
    TaskStatus::Success => {
        if let Some(video) = response.get_video_data() {
            println!("Video URL: {}", video.video_url);
            println!("Duration: {} seconds", video.duration);
            println!("Resolution: {}", video.resolution);
        }
    }
    TaskStatus::Failed => {
        eprintln!("Task failed: {}", response.msg);
    }
    _ => {
        println!("Task is still processing...");
    }
}
```

### Wait for Completion

```rust
let response = client.text2video()
    .wait_for_completion(&task_id, 5, 120)  // Poll every 5s, max 120 attempts
    .await?;

if let Some(video) = response.get_video_data() {
    println!("Video ready: {}", video.video_url);
}
```

## Error Handling

The SDK provides comprehensive error handling:

```rust
use skyreels_sdk::Error;

match client.text2video().get_task(&task_id).await {
    Ok(response) => { /* handle success */ }
    Err(Error::NetworkError(e)) => {
        eprintln!("Network error: {}", e);
    }
    Err(Error::ApiError { status, message }) => {
        eprintln!("API error ({}): {}", status, message);
    }
    Err(Error::TaskNotFound(task_id)) => {
        eprintln!("Task not found: {}", task_id);
    }
    Err(e) => {
        eprintln!("Error: {}", e);
    }
}
```

### Retry Logic

```rust
let mut attempts = 0;
let max_retries = 3;

loop {
    match client.text2video().get_task(&task_id).await {
        Ok(response) => break Ok(response),
        Err(e) if !e.is_retryable() || attempts >= max_retries => break Err(e),
        Err(_) => {
            attempts += 1;
            tokio::time::sleep(tokio::time::Duration::from_secs(2_u64.pow(attempts))).await;
        }
    }
}
```

## API Reference

### Aspect Ratio

- `Wide16x9` - 16:9 (landscape/widescreen, default)
- `Standard4x3` - 4:3 (standard landscape)
- `Square1x1` - 1:1 (square)
- `Portrait9x16` - 9:16 (portrait/mobile)
- `Standard3x4` - 3:4 (standard portrait)

### Mode

- `Fast` - Faster generation (coming soon)
- `Std` - Standard mode (default, currently supported)
- `Pro` - Professional mode (coming soon)

### Task Status

- `Submitted` - Task has been submitted
- `Pending` - Task is waiting in queue
- `Running` - Task is being processed
- `Success` - Task completed successfully
- `Failed` - Task failed
- `Unknown` - Unknown status

## Error Types

- `NetworkError` - Network or HTTP errors
- `ApiError` - API errors with status codes
- `InvalidParameter` - Invalid parameters provided
- `MissingApiKey` - API key not configured
- `SubmissionFailed` - Task submission failed
- `QueryFailed` - Task query failed
- `ResponseParseError` - Response parsing failed
- `TaskNotFound` - Task not found or invalid ID
- `RateLimitExceeded` - Rate limit exceeded
- `AuthenticationFailed` - Authentication failed

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.

## Support

- 📧 Email: support@skyreels.ai
- 🌐 Website: https://skyreels.ai
- 📚 Documentation: https://docs.skyreels.ai

## Acknowledgments

Built with:
- [reqwest](https://github.com/seanmonstar/reqwest) for HTTP requests
- [tokio](https://tokio.rs/) for async runtime
- [serde](https://serde.rs/) for serialization
- [thiserror](https://github.com/dtolnay/thiserror) for error handling
