namespace Books.Api.Infrastructure.FileStorage;

/// <summary>
/// Service for storing and retrieving attachment files.
/// Abstraction allows switching between local storage and cloud blob storage.
/// </summary>
public interface IFileStorageService
{
    /// <summary>
    /// Store a file and return the storage path.
    /// </summary>
    /// <param name="companyId">Company ID for organizing files</param>
    /// <param name="fileName">Original filename</param>
    /// <param name="contentType">MIME type</param>
    /// <param name="content">File content stream</param>
    /// <param name="cancellationToken">Cancellation token</param>
    /// <returns>Storage path for the file</returns>
    Task<StorageResult> StoreAsync(
        string companyId,
        string fileName,
        string contentType,
        Stream content,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// Retrieve a file by its storage path.
    /// </summary>
    /// <param name="storagePath">Storage path returned from StoreAsync</param>
    /// <param name="cancellationToken">Cancellation token</param>
    /// <returns>File content and metadata</returns>
    Task<FileResult> GetAsync(string storagePath, CancellationToken cancellationToken = default);

    /// <summary>
    /// Delete a file from storage.
    /// </summary>
    /// <param name="storagePath">Storage path to delete</param>
    /// <param name="cancellationToken">Cancellation token</param>
    Task DeleteAsync(string storagePath, CancellationToken cancellationToken = default);

    /// <summary>
    /// Get a URL for downloading/viewing a file.
    /// May return a signed URL with expiration for cloud storage.
    /// </summary>
    /// <param name="storagePath">Storage path</param>
    /// <param name="expiresIn">URL expiration time</param>
    /// <returns>Download URL</returns>
    string GetDownloadUrl(string storagePath, TimeSpan? expiresIn = null);
}

public record StorageResult
{
    public required string StoragePath { get; init; }
    public required string StoredFileName { get; init; }
    public required long FileSize { get; init; }
}

public record FileResult
{
    public required Stream Content { get; init; }
    public required string ContentType { get; init; }
    public required string FileName { get; init; }
    public required long FileSize { get; init; }
}
