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();
}
}