// Copyright 2025 SkyReels SDK Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use skyreels::{
    Mode, ReferenceImageType, ReferenceVideoType, SkyReelsClient,
};

/// Example 1: Keyframe video generation
///
/// This demonstrates how to create a video using keyframe images at specific timestamps.
#[tokio::main]
async fn example_keyframe_video() -> Result<(), Box<dyn std::error::Error>> {
    let client = SkyReelsClient::new("your_api_key");

    let request = client
        .omni()
        .submit_request(
            "The King @image1 anxiously searched for the destination on the map, \
             suddenly made a surprise discovery, ran out of the door, and summoned a flying dragon. \
             The dragon lowered its body @image2, the King mounted it, and the dragon took off. \
             The King rode the dragon forward, flying over a village @image3.",
        )
        .aspect_ratio("16:9")
        .duration(5)
        .add_reference_image(
            "@image1",
            ReferenceImageType::Keyframe,
            vec!["http://example.com/frame1.jpg".to_string()],
            Some(0),
        )
        .add_reference_image(
            "@image2",
            ReferenceImageType::Keyframe,
            vec!["http://example.com/frame2.jpg".to_string()],
            Some(2),
        )
        .add_reference_image(
            "@image3",
            ReferenceImageType::Keyframe,
            vec!["http://example.com/frame3.jpg".to_string()],
            Some(5),
        )
        .sound(false)
        .prompt_optimizer(true)
        .mode(Mode::Std)
        .build();

    let task_id = client.omni().submit(request).await?;
    println!("Keyframe video task submitted: {}", task_id);

    // Wait for completion
    let result = client
        .omni()
        .wait_for_completion(&task_id, 5, 120)
        .await?;

    if let Some(video) = result.get_video_data() {
        println!("Keyframe video ready: {}", video.video_url);
    }

    Ok(())
}

/// Example 2: Multi-subject reference video generation
///
/// This demonstrates how to use subject references to maintain character consistency.
#[tokio::main]
async fn example_subject_reference() -> Result<(), Box<dyn std::error::Error>> {
    let client = SkyReelsClient::new("your_api_key");

    let request = client
        .omni()
        .submit_request(
            "Captured in a gritty anime style, this sequence reveals @Actor-1 \
             caught in a moment of intense physical suffering. \
             @Actor-1 says with a strained and pained voice, \
             <dialogue>好痛，超痛的</dialogue>",
        )
        .aspect_ratio("16:9")
        .duration(5)
        .add_reference_image(
            "@Actor-1",
            ReferenceImageType::Subject,
            vec!["http://example.com/actor.jpg".to_string()],
            None,
        )
        .sound(true)
        .prompt_optimizer(true)
        .mode(Mode::Std)
        .build();

    let task_id = client.omni().submit(request).await?;
    println!("Subject reference task submitted: {}", task_id);

    Ok(())
}

/// Example 3: Grid reference image to video
///
/// This demonstrates how to use a grid of images as reference for video generation.
#[tokio::main]
async fn example_grid_reference() -> Result<(), Box<dyn std::error::Error>> {
    let client = SkyReelsClient::new("your_api_key");

    let request = client
        .omni()
        .submit_request(
            "Create a video showing how to make tomato and egg noodles based on the grid of pictures in @image1.",
        )
        .aspect_ratio("16:9")
        .duration(5)
        .add_reference_image(
            "@image1",
            ReferenceImageType::Image,
            vec!["http://example.com/grid.png".to_string()],
            None,
        )
        .sound(false)
        .prompt_optimizer(true)
        .mode(Mode::Std)
        .build();

    let task_id = client.omni().submit(request).await?;
    println!("Grid reference task submitted: {}", task_id);

    Ok(())
}

/// Example 4: Video motion reference
///
/// This demonstrates how to use a video as a motion reference.
#[tokio::main]
async fn example_motion_reference() -> Result<(), Box<dyn std::error::Error>> {
    let client = SkyReelsClient::new("your_api_key");

    let request = client
        .omni()
        .submit_request(
            "The man in @image_1 imitates the actions of the red male in @video_1, \
             and the monkey in @image_2 imitates the actions of the dog in @video_1, \
             while keeping the background of @video_1.",
        )
        .aspect_ratio("16:9")
        .duration(5)
        .add_reference_image(
            "@image_1",
            ReferenceImageType::Image,
            vec!["http://example.com/man.jpg".to_string()],
            None,
        )
        .add_reference_image(
            "@image_2",
            ReferenceImageType::Image,
            vec!["http://example.com/monkey.jpg".to_string()],
            None,
        )
        .add_reference_video(
            "@video_1",
            ReferenceVideoType::Reference,
            "http://example.com/reference.mp4",
        )
        .sound(false)
        .prompt_optimizer(true)
        .mode(Mode::Std)
        .build();

    let task_id = client.omni().submit(request).await?;
    println!("Motion reference task submitted: {}", task_id);

    Ok(())
}

/// Example 5: Video subject replacement
///
/// This demonstrates how to replace a subject in a video.
#[tokio::main]
async fn example_subject_replacement() -> Result<(), Box<dyn std::error::Error>> {
    let client = SkyReelsClient::new("your_api_key");

    let request = client
        .omni()
        .submit_request("Replace the rabbit in @video_1 with the velvet rabbit from @image_1.")
        .aspect_ratio("9:16")
        .add_reference_image(
            "@image_1",
            ReferenceImageType::Image,
            vec!["http://example.com/rabbit.jpg".to_string()],
            None,
        )
        .add_reference_video(
            "@video_1",
            ReferenceVideoType::Base,
            "http://example.com/base_video.mp4",
        )
        .sound(false)
        .prompt_optimizer(true)
        .mode(Mode::Std)
        .build();

    let task_id = client.omni().submit(request).await?;
    println!("Subject replacement task submitted: {}", task_id);

    Ok(())
}

/// Example 6: Video background replacement
///
/// This demonstrates how to replace the background in a video.
#[tokio::main]
async fn example_background_replacement() -> Result<(), Box<dyn std::error::Error>> {
    let client = SkyReelsClient::new("your_api_key");

    let request = client
        .omni()
        .submit_request(
            "Replace the background in @video_1 with the Pyramids of Giza from @image_1.",
        )
        .aspect_ratio("16:9")
        .add_reference_image(
            "@image_1",
            ReferenceImageType::Image,
            vec!["http://example.com/pyramids.png".to_string()],
            None,
        )
        .add_reference_video(
            "@video_1",
            ReferenceVideoType::Base,
            "http://example.com/base_video.mp4",
        )
        .sound(false)
        .prompt_optimizer(true)
        .mode(Mode::Std)
        .build();

    let task_id = client.omni().submit(request).await?;
    println!("Background replacement task submitted: {}", task_id);

    Ok(())
}

/// Example 7: Video object removal
///
/// This demonstrates how to remove an object from a video.
#[tokio::main]
async fn example_object_removal() -> Result<(), Box<dyn std::error::Error>> {
    let client = SkyReelsClient::new("your_api_key");

    let request = client
        .omni()
        .submit_request(
            "Remove the thin-framed gold spectacles from the man's hands and face in the central foreground of @video_1.",
        )
        .aspect_ratio("9:16")
        .add_reference_video(
            "@video_1",
            ReferenceVideoType::Base,
            "http://example.com/base_video.mp4",
        )
        .sound(false)
        .prompt_optimizer(true)
        .mode(Mode::Std)
        .build();

    let task_id = client.omni().submit(request).await?;
    println!("Object removal task submitted: {}", task_id);

    Ok(())
}

/// Example 8: Local video editing
///
/// This demonstrates how to edit specific parts of a video.
#[tokio::main]
async fn example_local_editing() -> Result<(), Box<dyn std::error::Error>> {
    let client = SkyReelsClient::new("your_api_key");

    let request = client
        .omni()
        .submit_request(
            "Replace the girl's clothing in @video_1 with the red superhero bodysuit from @image_1.",
        )
        .aspect_ratio("9:16")
        .add_reference_image(
            "@image_1",
            ReferenceImageType::Image,
            vec!["http://example.com/suit.png".to_string()],
            None,
        )
        .add_reference_video(
            "@video_1",
            ReferenceVideoType::Base,
            "http://example.com/base_video.mp4",
        )
        .sound(false)
        .prompt_optimizer(true)
        .mode(Mode::Std)
        .build();

    let task_id = client.omni().submit(request).await?;
    println!("Local editing task submitted: {}", task_id);

    Ok(())
}

/// Main entry point - run all examples
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    println!("=== SkyReels SDK Omni API Examples ===\n");

    // Note: These examples won't actually run without valid API keys and URLs
    // They serve as documentation for how to use the omni API

    println!("Example 1: Keyframe video generation");
    println!("Example 2: Multi-subject reference video generation");
    println!("Example 3: Grid reference image to video");
    println!("Example 4: Video motion reference");
    println!("Example 5: Video subject replacement");
    println!("Example 6: Video background replacement");
    println!("Example 7: Video object removal");
    println!("Example 8: Local video editing");

    println!("\nTo run these examples, update the API keys and URLs, then call the individual example functions.");

    Ok(())
}
