using System.Text.Json.Serialization;
using MaBibli.Shared.Entites;
using MaBibli.Shared.Textes;
namespace MaBibli.Shared.Dtos;
///
/// Charge utile de création et de modification d'un livre.
///
///
/// n'y figure pas volontairement : il est déterminé par le serveur
/// à partir de l'utilisateur authentifié, jamais par le client.
///
public record EnregistrementLivre
{
/// Séparateur des auteurs dans la forme texte d'un champ de saisie.
///
/// Le point-virgule, et non la virgule : celle-ci est déjà prise par la forme
/// bibliographique « Zola, Émile », qu'on doit pouvoir taper telle quelle.
///
public const char SeparateurAuteurs = ';';
/// Facultatif : certains livres n'ont pas d'ISBN. Normalisé par le serveur.
public string? Isbn { get; set; }
public string Titre { get; set; } = string.Empty;
///
/// Auteurs, dans l'ordre de la couverture, chacun avec son rôle sur ce livre. Le
/// serveur les rattache aux fiches existantes quand c'est sûr, et en crée sinon.
///
public List Auteurs { get; set; } = [];
/// Thèmes saisis manuellement, séparés par des points-virgules dans l'interface.
public List Themes { get; set; } = [];
public string? Editeur { get; set; }
public Format Format { get; set; }
/// Roman, bande dessinée… Facultatif : « non précisé » est une réponse valable.
public TypeDocument TypeDocument { get; set; }
///
/// Statut de lecture de l'appelant. null = non commencé, et aucune ligne n'est
/// alors écrite en base.
///
public Statut? Statut { get; set; }
///
/// Nombre de pages. null = non renseigné, et surtout pas 0.
///
///
/// Peut arriver prérempli depuis dc:format de la BnF ; c'est alors une
/// proposition, que la saisie corrige ou efface.
///
public int? NombrePages { get; set; }
public string? CoverUrl { get; set; }
///
/// Notice ayant servi au préremplissage, ou null pour une saisie manuelle.
///
public string? UrlNotice { get; set; }
///
/// Vue « une seule ligne » de , pour les champs de saisie simples.
///
///
/// ⚠️ Ce n'est plus un champ de saisie : le formulaire remplit la liste un auteur à
/// la fois (voir SaisieListe), un champ relié à chaque frappe sur cette propriété
/// ayant rendu son propre séparateur intapable. Elle ne sert plus qu'au préremplissage
/// depuis une notice, qui donne les auteurs sur une ligne — une seule affectation, jamais
/// une par caractère.
///
[JsonIgnore]
public string? Auteur
{
get => Auteurs.Count == 0 ? null : string.Join($"{SeparateurAuteurs} ", Auteurs.Select(a => a.Nom));
set => Auteurs = Decouper(value, Auteurs);
}
///
/// Découpe une saisie texte en auteurs, en écartant les entrées vides.
///
///
/// Auteurs déjà saisis, dont les rôles sont repris quand le nom réapparaît.
///
///
/// ⚠️ La reprise des rôles a été écrite pour un champ qui se reconstruisait à chaque frappe.
/// Ce champ n'existe plus — le formulaire corrige un nom sans toucher à son rôle
/// (NomsAuteurs) — mais elle reste juste, et gratuite, pour un préremplissage qui
/// écraserait sinon des rôles déjà posés.
///
public static List Decouper(string? saisie, IEnumerable? connus = null)
{
if (string.IsNullOrWhiteSpace(saisie))
{
return [];
}
var roles = new Dictionary(StringComparer.Ordinal);
foreach (var connu in connus ?? [])
{
roles.TryAdd(NormalisationTexte.Normaliser(connu.Nom), connu.Role);
}
return saisie
.Split(SeparateurAuteurs, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
.Select(nom => new AuteurSaisi(
nom, roles.GetValueOrDefault(NormalisationTexte.Normaliser(nom), RoleAuteur.NonPrecise)))
.ToList();
}
///
/// Découpe une ligne de thèmes. Séparateur : le point-virgule, la virgule restant
/// acceptée — un thème n'en contient jamais.
///
/// ⚠️ Plus aucun champ ne s'y lie : les thèmes se saisissent un par un. Cela reste la façon
/// de relire une ligne venue d'ailleurs.
///
///
public static List DecouperThemes(string? saisie) =>
ListeSaisie.Decouper(saisie);
}
/// Un auteur tel qu'il est saisi : son nom, et son rôle sur ce livre.
///
/// Le rôle n'appartient pas à la personne mais au lien : le même auteur scénarise un
/// album et dessine le suivant. Voir .
///
public record AuteurSaisi(string Nom, RoleAuteur Role = RoleAuteur.NonPrecise);
/// Demande de renommage d'une fiche auteur.
public record RenommerAuteur(string Nom);
/// Résultat d'un renommage, avec collision éventuelle à confirmer.
public record ResultatRenommageAuteur
{
public AuteurDto? Auteur { get; init; }
public AuteurDto? Collision { get; init; }
public bool EstCollision => Collision is not null;
}
/// Charge utile du changement de statut de lecture — l'action la plus fréquente.
///
/// Le statut posé est toujours celui de l'appelant : il n'y a pas de champ « utilisateur »,
/// et il ne doit jamais y en avoir. Personne ne coche « lu » à la place d'un autre.
///
public record ChangementStatut
{
/// null retire le statut : le livre redevient « non commencé » pour l'appelant.
public Statut? Statut { get; set; }
}