//! Trait abstraction over S3 operations for testability.
//!
//! The engine uses `S3Operations` rather than the AWS SDK `Client` directly,
//! allowing mock implementations for testing without any AWS access.

use std::future::Future;
use std::pin::Pin;

use crate::error::S3boltError;
use crate::types::{ObjectInfo, S3Uri};

/// Result type for async S3 operations.
pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;

/// Abstraction over S3 operations used by the copy engine.
///
/// Implement this trait to provide real S3 access (via AWS SDK) or
/// mock implementations for testing.
pub trait S3Operations: Send + Sync + 'static {
    /// List all objects under a prefix. Returns a vec of object metadata.
    fn list_objects(&self, uri: &S3Uri) -> BoxFuture<'_, Result<Vec<ObjectInfo>, S3boltError>>;

    /// Copy a single object (server-side, ≤ 5 GiB).
    /// Returns the destination ETag on success.
    fn copy_object(
        &self,
        source: &S3Uri,
        destination: &S3Uri,
        storage_class: Option<&str>,
    ) -> BoxFuture<'_, Result<String, S3boltError>>;

    /// Copy a large object using multipart server-side copy (> 5 GiB).
    /// Returns the destination ETag on success.
    fn copy_object_multipart(
        &self,
        source: &S3Uri,
        destination: &S3Uri,
        object_size: u64,
        part_size: u64,
        storage_class: Option<&str>,
    ) -> BoxFuture<'_, Result<String, S3boltError>>;

    /// Check if an object exists at the destination and return its ETag + size.
    /// Used for sync mode.
    fn head_object(&self, uri: &S3Uri)
    -> BoxFuture<'_, Result<Option<(String, u64)>, S3boltError>>;
}
