using System; using System.IO; using System.Net.Http; using System.Text.Json; using System.Threading.Tasks; using DysonNetwork.Common.Interfaces; using DysonNetwork.Common.Models; using Microsoft.Extensions.Logging; using NodaTime; using NodaTime.Serialization.SystemTextJson; namespace DysonNetwork.Common.Clients { public class FileServiceClient : IFileServiceClient, IDisposable { private readonly HttpClient _httpClient; private readonly ILogger _logger; private readonly JsonSerializerOptions _jsonOptions; public FileServiceClient(HttpClient httpClient, ILogger logger) { _httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _jsonOptions = new JsonSerializerOptions().ConfigureForNodaTime(DateTimeZoneProviders.Tzdb); _jsonOptions.PropertyNameCaseInsensitive = true; } public async Task GetFileAsync(string fileId) { var response = await _httpClient.GetAsync($"api/files/{fileId}"); response.EnsureSuccessStatusCode(); await using var stream = await response.Content.ReadAsStreamAsync(); var file = await JsonSerializer.DeserializeAsync(stream, _jsonOptions); return file; } public async Task GetFileStreamAsync(string fileId) { if (string.IsNullOrEmpty(fileId)) throw new ArgumentNullException(nameof(fileId)); var response = await _httpClient.GetAsync($"api/files/{fileId}/download"); response.EnsureSuccessStatusCode(); var stream = await response.Content.ReadAsStreamAsync(); if (stream == null) throw new InvalidOperationException("Failed to read file stream from response."); return stream; } public async Task UploadFileAsync(Stream fileStream, string fileName, string? contentType = null) { using var content = new MultipartFormDataContent(); var fileContent = new StreamContent(fileStream); if (!string.IsNullOrEmpty(contentType)) { fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(contentType); } content.Add(fileContent, "file", fileName); var response = await _httpClient.PostAsync("api/files/upload", content); response.EnsureSuccessStatusCode(); await using var responseStream = await response.Content.ReadAsStreamAsync(); var file = await JsonSerializer.DeserializeAsync(responseStream, _jsonOptions); return file; } public async Task ProcessImageAsync(Stream imageStream, string fileName, string? contentType = null) { using var content = new MultipartFormDataContent(); var fileContent = new StreamContent(imageStream); if (!string.IsNullOrEmpty(contentType)) { fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(contentType); } content.Add(fileContent, "image", fileName); var response = await _httpClient.PostAsync("api/files/process-image", content); response.EnsureSuccessStatusCode(); await using var responseStream = await response.Content.ReadAsStreamAsync(); var file = await JsonSerializer.DeserializeAsync(responseStream, _jsonOptions); return file; } public async Task GetFileUrl(string fileId, bool useCdn = false) { var url = $"api/files/{fileId}/url"; if (useCdn) { url += "?useCdn=true"; } var response = await _httpClient.GetAsync(url); response.EnsureSuccessStatusCode(); var result = await response.Content.ReadAsStringAsync(); return result.Trim('"'); } public async Task DeleteFileAsync(string fileId) { var response = await _httpClient.DeleteAsync($"api/files/{fileId}"); response.EnsureSuccessStatusCode(); } public void Dispose() { _httpClient?.Dispose(); GC.SuppressFinalize(this); } } }