using Butter.Dtos.Person; using Microsoft.Extensions.Options; namespace MilkStream.Client.Services; /// /// Provides access to person data via the API. /// public sealed class PersonService( IOptions options, IHttpClientFactory httpClientFactory, LoginService loginService, ILogger logger ) : AuthServiceBase(options, httpClientFactory, loginService, logger) { /// /// Gets a paginated list of people with optional search and sort options. /// /// The zero-based page number. /// The number of items per page. /// Optional search term to filter by name. /// Optional field to sort by (e.g. "name", "created", "albums"). /// Whether to sort ascending. Default is true. /// A list of person previews, or null if the request failed. public async Task?> GetAllAsync(int page = 0, int pageSize = 30, string? search = null, string? sortBy = null, bool sortAsc = true) { var url = $"/api/person?page={page}&pageSize={pageSize}"; if (!string.IsNullOrEmpty(search)) url += $"&search={Uri.EscapeDataString(search)}"; if (!string.IsNullOrEmpty(sortBy)) url += $"&sortBy={Uri.EscapeDataString(sortBy)}"; url += $"&sortAsc={sortAsc.ToString().ToLowerInvariant()}"; var response = await Client.GetAsync(url); if (response.IsSuccessStatusCode) return await response.Content.ReadFromJsonAsync>(); return null; } /// /// Gets a person by ID with albums and stats. /// /// The person ID. /// Optional zero-based page number for albums. /// Optional number of albums per page. /// Optional search term to filter album titles. /// Optional field to sort albums by (e.g. "name", "created", "updated", "assets"). /// Whether to sort ascending. Default is true. /// The person details, or null if not found. public async Task GetByIdAsync(Guid id, int? albumPage = null, int? albumPageSize = null, string? search = null, string? sortBy = null, bool sortAsc = true) { var url = $"/api/person/{id}"; var hasParams = false; if (albumPage.HasValue && albumPageSize.HasValue) { url += $"?page={albumPage}&pageSize={albumPageSize}"; hasParams = true; } if (!string.IsNullOrEmpty(search)) { url += $"{(hasParams ? "&" : "?")}search={Uri.EscapeDataString(search)}"; hasParams = true; } if (!string.IsNullOrEmpty(sortBy)) { url += $"{(hasParams ? "&" : "?")}sortBy={Uri.EscapeDataString(sortBy)}"; hasParams = true; } url += $"{(hasParams ? "&" : "?")}sortAsc={sortAsc.ToString().ToLowerInvariant()}"; var response = await Client.GetAsync(url); if (response.IsSuccessStatusCode) return await response.Content.ReadFromJsonAsync(); return null; } /// /// Updates a person's name and profile asset. /// /// The person ID. /// The updated person data. public async Task UpdatePersonAsync(Guid id, PersonUpdateDto dto) { var response = await Client.PostAsJsonAsync($"/api/person/{id}", dto); response.EnsureSuccessStatusCode(); } /// /// Creates a new person. /// /// The person creation data. /// The new person's ID, or null if the request failed. public async Task CreatePersonAsync(PersonCreateDto dto) { var response = await Client.PutAsJsonAsync("/api/person", dto); if (response.IsSuccessStatusCode) return await response.Content.ReadFromJsonAsync(); return null; } /// /// Soft-deletes a person. /// /// The person ID. public async Task DeletePersonAsync(Guid id) { var response = await Client.DeleteAsync($"/api/person/{id}"); response.EnsureSuccessStatusCode(); } }