using MaBibli.Shared.Isbn;
using MaBibli.Shared.Textes;
namespace MaBibli.Shared.Entites;
///
/// Une revue — ou un numéro précis — que l'on aimerait acquérir. Personnelle, comme
/// .
///
///
/// Pourquoi une table sœur plutôt que des colonnes de plus sur ?
/// Une envie de livre est identifiée par un couple (œuvre, auteur) : c'est ce que porte son index
/// unique, et c'est ce qui permet de la rapprocher du catalogue. Un numéro de revue n'a
/// pas d'auteur et se distingue par son numéro — deux notions que la clé de
/// LivreSouhaite ne sait pas exprimer sans devenir fausse pour tout le monde. Y loger les
/// revues aurait obligé à écrire « et qui n'est pas une revue » à chaque rapprochement, à chaque
/// export et à chaque compteur : c'est exactement le raisonnement qui a séparé
/// de .
///
/// ⚠️ Le coût est assumé et il est réel : deux tables se fusionnent à l'affichage, dans
/// les deux exports et dans l'instantané hors-ligne. C'est là que le sujet se rate s'il est
/// bâclé — une envie de revue invisible en librairie ne sert à rien.
///
///
/// est une frontière, pas une trace : aucun point d'entrée
/// n'accepte de nom d'utilisateur, et l'envie d'un autre répond 404, jamais 403.
///
///
public class RevueSouhaitee
{
public int Id { get; set; }
///
/// YNH_USER du propriétaire de l'envie. Frontière : toute lecture filtre dessus.
///
public string Utilisateur { get; set; } = string.Empty;
/// Titre de la revue (« Médor »), sans son numéro.
public string Titre { get; set; } = string.Empty;
/// Titre mis à plat. Sert au dédoublonnage.
///
/// ⚠️ et non CleOeuvre : le titre d'une revue n'a ni
/// mention de responsabilité ni sous-titre à couper, et « Médor : les yeux ouverts » est une
/// accroche qu'on ne tape pas. C'est la même règle que .
///
public string TitreNormalise { get; set; } = string.Empty;
///
/// Numéro souhaité (« 43 », « hors-série 7 »), ou null pour la revue entière.
///
///
/// Facultatif, et c'est la moitié du besoin : on souhaite parfois un numéro précis vu en
/// kiosque, parfois l'abonnement à un titre qu'on ne possède pas encore.
///
public string? Numero { get; set; }
///
/// Numéro mis à plat. Jamais null — chaîne vide pour « la revue entière ».
///
///
/// ⚠️ Même piège que : SQLite tient deux
/// NULL pour distincts, et l'unicité laisserait alors passer autant de fois « Médor,
/// pas de numéro » qu'on voudrait.
///
public string NumeroNormalise { get; set; } = string.Empty;
///
/// ISSN, facultatif, canonisé avec son tiret (« 2466-6718 »).
///
///
/// C'est la forme rangée en base pour tout le projet — seule exception à « la valeur stockée
/// reste nue », l'ISSN étant produit à tiret par le code-barres et interrogé à tiret par la
/// BnF. Sans canonisation, un ISSN tapé « 24666718 » ne se rapprocherait de rien.
///
public string? Issn { get; set; }
/// Note libre : « vu chez le dentiste », « demander au kiosque ».
public string? Note { get; set; }
public DateTime DateAjout { get; set; }
///
/// Rang dans la section « revues » de la liste, du plus désiré au moins désiré.
///
///
/// ⚠️ Cette numérotation est indépendante de celle de :
/// chaque table repart de zéro par utilisateur. C'est précisément pourquoi la liste affiche
/// deux sections plutôt qu'un seul classement entrelacé — deux suites de rangs sans rapport
/// mélangées produiraient un ordre que personne n'a choisi.
///
public int Rang { get; set; }
public void RecalculerFormes()
{
Titre = Titre.Trim();
TitreNormalise = NormalisationTexte.Normaliser(Titre);
Numero = string.IsNullOrWhiteSpace(Numero) ? null : Numero.Trim();
NumeroNormalise = Numero is null ? string.Empty : NormalisationTexte.Normaliser(Numero);
// Canonique() rend la saisie élaguée quand ce n'est pas un ISSN : un code mal recopié
// est conservé tel quel plutôt que jeté — le voir mal formé vaut mieux que le voir
// disparaître.
Issn = FormatageIssn.Canonique(Issn);
}
}