use lmrc_docker::{DockerClient, Result};

#[tokio::main]
async fn main() -> Result<()> {
    // Create a Docker client
    let client = DockerClient::new()?;

    // Check Docker is available
    println!("Pinging Docker daemon...");
    client.ping().await?;
    println!("Connected to Docker daemon\n");

    // Get registry operations handle
    let registry = client.registry();

    // Example 1: Search for images in Docker Hub
    println!("=== Searching for 'nginx' images ===");
    let results = registry.search("nginx", Some(5)).await?;
    for result in results {
        println!(
            "  {} - {} stars - {}",
            result.name,
            result.star_count.unwrap_or(0),
            result
                .description
                .unwrap_or_else(|| "No description".to_string())
        );
    }
    println!();

    // Example 2: Check if an image exists locally
    println!("=== Checking local images ===");
    let image_name = "alpine:latest";
    let exists = registry.image_exists_locally(image_name).await?;
    println!("Image '{}' exists locally: {}", image_name, exists);
    println!();

    // Example 3: List all local images
    println!("=== Listing local images ===");
    let images = registry.list_local_images(false).await?;
    println!("Found {} local images:", images.len());
    for image in images.iter().take(5) {
        let repo_tags = image.repo_tags.clone();
        let size_mb = image.size as f64 / 1_000_000.0;
        println!("  {} - {:.2} MB", repo_tags.join(", "), size_mb);
    }
    println!();

    // Example 4: Pull an image if it doesn't exist
    if !exists {
        println!("=== Pulling {} ===", image_name);
        client.images().pull(image_name, None).await?;
        println!("Image pulled successfully\n");
    }

    // Example 5: Inspect a local image
    println!("=== Inspecting {} ===", image_name);
    let inspect = registry.inspect_image(image_name).await?;
    println!("Image ID: {}", inspect.id.unwrap_or_default());
    println!("Architecture: {}", inspect.architecture.unwrap_or_default());
    println!("OS: {}", inspect.os.unwrap_or_default());
    if let Some(size) = inspect.size {
        println!("Size: {:.2} MB", size as f64 / 1_000_000.0);
    }
    println!();

    // Example 6: Tag an image
    println!("=== Tagging image ===");
    let new_tag = "my-alpine";
    registry
        .tag_image(image_name, new_tag, Some("test"))
        .await?;
    println!("Tagged {} as {}:test", image_name, new_tag);
    println!();

    // Example 7: Verify the new tag exists
    let tagged_exists = registry
        .image_exists_locally(&format!("{}:test", new_tag))
        .await?;
    println!("New tag '{}:test' exists: {}", new_tag, tagged_exists);
    println!();

    // Example 8: Export an image to tar
    println!("=== Exporting image ===");
    let tar_data = registry.export_image(image_name).await?;
    println!("Exported image to tar: {} bytes", tar_data.len());
    println!();

    // Example 9: Remove the tagged image
    println!("=== Cleaning up tagged image ===");
    registry
        .remove_image(&format!("{}:test", new_tag), false, false)
        .await?;
    println!("Removed tagged image\n");

    // Example 10: Prune dangling images
    println!("=== Pruning dangling images ===");
    let reclaimed = registry.prune_images(true).await?;
    println!("Reclaimed {} bytes from dangling images", reclaimed);
    println!();

    // Example 11: Registry authentication (for private registries)
    println!("=== Registry authentication example ===");
    println!("To authenticate with Docker Hub:");
    println!("  let config = RegistryConfig::docker_hub(");
    println!("      \"username\".to_string(),");
    println!("      \"password_or_token\".to_string()");
    println!("  );");
    println!("  registry.login(&config).await?;");
    println!();

    println!("To authenticate with GitHub Container Registry:");
    println!("  let config = RegistryConfig::github(");
    println!("      \"username\".to_string(),");
    println!("      \"github_personal_access_token\".to_string()");
    println!("  );");
    println!("  registry.login(&config).await?;");
    println!();

    println!("To authenticate with a custom registry:");
    println!("  let config = RegistryConfig::custom(\"registry.example.com\".to_string())");
    println!("      .with_auth(\"username\".to_string(), \"password\".to_string());");
    println!("  registry.login(&config).await?;");
    println!();

    // Example 12: After authentication, you can push images
    println!("=== Pushing images (requires authentication) ===");
    println!("After authentication, push images using the images API:");
    println!("  client.images().push(\"username/image:tag\", None).await?;");
    println!();

    println!("Registry operations examples completed successfully!");

    Ok(())
}
