using MediatR;
using StorageService.Domain.AggregatesModel.FileAggregate;

namespace StorageService.API.Application.Commands;

/// <summary>
/// EN: Command to request a pre-signed URL for direct upload.
/// VI: Command để yêu cầu pre-signed URL cho upload trực tiếp.
/// </summary>
/// <remarks>
/// EN: This enables Direct Client Upload pattern where files are uploaded directly to MinIO,
///     bypassing the backend to handle millions of concurrent uploads efficiently.
/// VI: Pattern này cho phép upload trực tiếp lên MinIO, bỏ qua backend để xử lý 
///     hàng triệu uploads đồng thời một cách hiệu quả.
/// </remarks>
/// <param name="UserId">EN: User ID requesting upload / VI: ID người dùng yêu cầu upload</param>
/// <param name="FileName">EN: Original file name / VI: Tên file gốc</param>
/// <param name="ContentType">EN: MIME content type / VI: Content type MIME</param>
/// <param name="FileSizeBytes">EN: File size in bytes for quota check / VI: Kích thước file (bytes) để kiểm tra quota</param>
/// <param name="AccessLevel">EN: Access level: Public, Private, or Shared / VI: Mức truy cập: Public, Private, hoặc Shared</param>
/// <param name="TenantId">EN: Optional tenant ID / VI: Tenant ID (tùy chọn)</param>
public record SignUploadCommand(
    string UserId,
    string FileName,
    string ContentType,
    long FileSizeBytes,
    FileAccessLevel AccessLevel = FileAccessLevel.Private,
    string? TenantId = null
) : IRequest<SignUploadResult>;

/// <summary>
/// EN: Result of sign upload request containing pre-signed URL.
/// VI: Kết quả yêu cầu sign upload chứa pre-signed URL.
/// </summary>
/// <param name="Success">EN: Whether the request was successful / VI: Yêu cầu có thành công không</param>
/// <param name="UploadUrl">EN: Pre-signed URL for PUT request / VI: Pre-signed URL cho PUT request</param>
/// <param name="ObjectKey">EN: Object key in storage / VI: Object key trong storage</param>
/// <param name="ExpiresAt">EN: URL expiration time / VI: Thời gian hết hạn URL</param>
/// <param name="Error">EN: Error message if failed / VI: Thông báo lỗi nếu thất bại</param>
public record SignUploadResult(
    bool Success,
    string? UploadUrl,
    string? ObjectKey,
    DateTime? ExpiresAt,
    string? Error
)
{
    /// <summary>
    /// EN: Create a successful result.
    /// VI: Tạo kết quả thành công.
    /// </summary>
    public static SignUploadResult Ok(string uploadUrl, string objectKey, DateTime expiresAt) =>
        new(true, uploadUrl, objectKey, expiresAt, null);

    /// <summary>
    /// EN: Create a failed result.
    /// VI: Tạo kết quả thất bại.
    /// </summary>
    public static SignUploadResult Fail(string error) =>
        new(false, null, null, null, error);
}
