using Microsoft.Extensions.Logging; using mws.backend.dotnet.application.Common; using mws.backend.dotnet.application.Documents; namespace mws.backend.dotnet.infrastructure.CloudFile; public class CloudFileDocumentContentStore( ICloudFileHttpClient cf, ILogger log) : IDocumentContentStore { private static string Bucket(Guid projectId) => $"mws-p-{projectId:N}"; private static string Key(Guid documentId) => $"{documentId:N}.html"; public Task EnsureBucketAsync(Guid projectId, CancellationToken ct) => cf.EnsureBucketAsync(Bucket(projectId), ct); public async Task UploadAsync(Guid projectId, Guid documentId, string contentType, Stream body, CancellationToken ct) { try { var meta = await cf.UploadAsync(Bucket(projectId), Key(documentId), contentType, body, ct); log.LogDebug("Uploaded document {DocumentId} to cloudfile: {Hash}", documentId, meta?.ContentHash); } catch (HttpRequestException ex) { log.LogError(ex, "CloudFile upload failed for document {DocumentId}", documentId); throw new StorageUnavailableException("Cloud file upload failed", ex); } } public async Task DownloadAsync(Guid projectId, Guid documentId, CancellationToken ct) { try { return await cf.DownloadAsync(Bucket(projectId), Key(documentId), ct); } catch (HttpRequestException ex) { log.LogError(ex, "CloudFile download failed for document {DocumentId}", documentId); throw new StorageUnavailableException("Cloud file download failed", ex); } } public async Task ExistsAsync(Guid projectId, Guid documentId, CancellationToken ct) { try { return await cf.ExistsAsync(Bucket(projectId), Key(documentId), ct); } catch (HttpRequestException) { return false; } } public async Task DeleteAsync(Guid projectId, Guid documentId, CancellationToken ct) { var bucket = Bucket(projectId); var key = Key(documentId); log.LogInformation("CloudFile delete: bucket={Bucket}, key={Key}", bucket, key); try { await cf.DeleteAsync(bucket, key, ct); log.LogInformation("CloudFile delete OK for document {DocumentId}", documentId); } catch (HttpRequestException ex) { log.LogWarning(ex, "CloudFile delete failed for document {DocumentId} (bucket={Bucket}, key={Key})", documentId, bucket, key); } } }