namespace MaBibli.Shared.Dtos;
///
/// Une série telle qu'exposée par l'API — trilogie, cycle, intégrale.
///
///
/// La liste est rendue à plat, chaque série portant l'identifiant de sa parente, et c'est
/// le client qui rebâtit l'arbre. Deux raisons : un JSON récursif se cache mal dans un
/// instantané hors-ligne, et une seule lecture suffit alors à servir la liste et le
/// détail — donc un seul instantané à tenir à jour.
///
public record SerieDto
{
public required int Id { get; init; }
public required string Titre { get; init; }
/// La série qui contient celle-ci, si elle fait partie d'un cycle.
public int? SerieParenteId { get; init; }
/// Rang dans la série parente. Sans objet à la racine.
public int Position { get; init; }
/// Les tomes, dans l'ordre de lecture.
public IReadOnlyList Elements { get; init; } = [];
/// Qui a créé la série. Trace d'affichage : la série est commune au foyer.
public string? AjoutePar { get; init; }
/// Tomes possédés sur tomes recensés — « 4 sur 7 », le cœur de l'écran.
public int NombrePossedes => Elements.Count(e => e.Possede);
}
///
/// Une place dans l'ordre de lecture, occupée ou non.
///
///
/// ⚠️ Un élément sans n'est pas une anomalie : c'est un tome qu'on
/// ne possède pas, et c'est précisément ce que l'écran doit montrer.
///
public record ElementSerieDto
{
public required int Id { get; init; }
public int Position { get; init; }
/// Titre du tome : celui du livre quand il est rattaché, sinon celui qui a été saisi.
public required string Titre { get; init; }
public int? LivreId { get; init; }
public bool Possede => LivreId is not null;
/// Auteurs du livre rattaché, pour ne pas avoir à ouvrir sa fiche.
public string? Auteurs { get; init; }
/// À qui le tome est prêté, s'il est dehors. Commun au foyer, comme tout prêt.
public string? PreteA { get; init; }
}
/// Charge utile de création ou de renommage d'une série.
public record EnregistrementSerie
{
public string Titre { get; set; } = string.Empty;
/// Série parente, pour ranger une trilogie dans un cycle. null = à la racine.
public int? SerieParenteId { get; set; }
}
///
/// Charge utile d'ajout d'un tome : soit un livre du catalogue, soit un simple titre.
///
///
/// Les deux voies existent parce qu'une saga se recense d'un coup — souvent avant d'en posséder
/// la moitié — puis se remplit au fil des achats.
///
public record AjoutElementSerie
{
/// Livre du catalogue à placer ici. null = un tome qu'on ne possède pas.
public int? LivreId { get; set; }
/// Titre du tome. Obligatoire sans livre ; repris du livre sinon.
public string? Titre { get; set; }
}
/// Nouvel ordre de lecture : la liste entière des identifiants d'éléments.
///
/// Comme pour la liste d'envies, on prend la liste complète plutôt qu'un déplacement unitaire :
/// une seule opération à vérifier, et c'est ce dont a besoin le glisser-déposer comme les
/// flèches.
///
public record OrdreElementsSerie
{
public List Ids { get; set; } = [];
}
/// Nouvel ordre des séries directement contenues dans un cycle.
public record OrdreSeries
{
public List Ids { get; set; } = [];
}
/// Déplacement d'une série dans l'ordre de lecture de son cycle.
public readonly record struct DeplacementSerie(int SerieId, int ParenteId, int Delta);