using MaBibli.Shared.Isbn;
using MaBibli.Shared.Textes;
namespace MaBibli.Shared.Entites;
///
/// Une revue — magazine, périodique —, et non l'un de ses numéros.
///
///
/// Pourquoi une table à part et non une ligne de Livres ? Même raisonnement que
/// pour et , et il vaut d'être répété : logée
/// dans Livres, une revue entrerait mécaniquement dans le catalogue, ses
/// compteurs, la détection de doublons, les séries et les bibliographies par auteur — et il
/// faudrait écrire « et qui n'est pas une revue » à chaque lecture. Un invariant qu'on réécrit
/// partout finit par être oublié quelque part.
///
/// Une fiche par revue, les numéros à l'intérieur. C'est ce qui évite le défaut redouté
/// dès le premier lot : douze numéros d'un même magazine ne font pas douze fiches identiques,
/// puisqu'ils partagent la fiche de leur revue.
///
///
/// ⚠️ L' est un identifiant de revue, jamais un ISBN. Ranger un code
/// 977 dans Livre.Isbn ferait échouer tout lookup ultérieur sur cette fiche —
/// c'est précisément ce que cette table évite.
///
///
public class Revue
{
public int Id { get; set; }
public string Titre { get; set; } = string.Empty;
/// Titre mis à plat. Index unique : une revue, une fiche.
public string TitreNormalise { get; set; } = string.Empty;
///
/// ISSN sous sa forme canonique à tiret (2466-6718), quand on le connaît.
///
///
/// Facultatif : une revue se catalogue à la main sans que personne n'ait scanné son
/// code-barres. Son unicité est portée par un index partiel — deux NULL sont
/// distincts pour SQLite, une unicité simple laisserait donc passer autant de revues sans
/// ISSN qu'on veut, ce qui est justement le comportement voulu.
///
public string? Issn { get; set; }
public string? Editeur { get; set; }
public DateTime DateAjout { get; set; }
/// Trace de saisie. Pas une frontière : les revues sont communes au foyer.
public string? AjoutePar { get; set; }
public List Numeros { get; set; } = [];
public void RecalculerFormes()
{
Titre = Titre.Trim();
TitreNormalise = NormalisationTexte.Normaliser(Titre);
// ⚠️ L'ISSN est rangé sous sa forme À TIRET, et ce n'est pas de la cosmétique : c'est
// celle que produit le code-barres (CodePeriodique.IssnDepuis) et celle qu'interroge
// bib.issn à la BnF. Un ISSN tapé « 24666718 » ne se serait rapproché de rien.
Issn = FormatageIssn.Canonique(Issn);
}
}
///
/// Un numéro possédé d'une revue.
///
///
/// Décidé le 2026-08-19 : un numéro est recensé, rien de plus. Ni prêt, ni statut de
/// lecture — ces deux mécanismes sont attachés à par clé étrangère, et les
/// rouvrir demanderait une seconde table de prêts ou une parenté commune, pour un usage non
/// confirmé. Le choix est réversible : les ajouter plus tard ne détruit rien de ce qui
/// est enregistré ici.
///
public class NumeroRevue
{
public int Id { get; set; }
public int RevueId { get; set; }
public Revue? Revue { get; set; }
///
/// Le numéro tel qu'il est imprimé (« 43 », « hors-série 7 »). Obligatoire :
/// sans lui, deux numéros de la même revue seraient indiscernables.
///
public string Numero { get; set; } = string.Empty;
/// Forme mise à plat, porteuse de l'unicité au sein de la revue.
public string NumeroNormalise { get; set; } = string.Empty;
/// Date de parution, quand elle est connue. En UTC comme toutes les dates.
public DateTime? DateParution { get; set; }
/// Note libre : « dossier sur l'eau », « prêté à Paul », « acheté en gare ».
public string? Note { get; set; }
///
/// URL d'une image de couverture, collée à la main.
///
///
/// ⚠️ Aucune source ne peut la fournir, contrairement aux livres : l'ISSN désigne la
/// revue, pas la parution, et OpenLibrary n'a donc rien à en dire. C'est pourquoi ce
/// champ n'est alimenté que par une URL saisie — et pourquoi l'écran n'en propose aucune.
///
/// ⚠️ Une image de numéro doit être connue du relais
/// (GET /api/couvertures) au même titre que celle d'un livre ou d'une envie, sans
/// quoi elle s'afficherait en ligne et jamais hors-ligne — exactement le défaut corrigé le
/// 2026-08-20 pour les hébergeurs sans CORS.
///
///
public string? CoverUrl { get; set; }
/// Articles annoncés à la une, dans l'ordre de saisie.
public List Articles { get; set; } = [];
public DateTime DateAjout { get; set; }
public void RecalculerFormes()
{
Numero = Numero.Trim();
NumeroNormalise = NormalisationTexte.Normaliser(Numero);
CoverUrl = string.IsNullOrWhiteSpace(CoverUrl) ? null : CoverUrl.Trim();
}
}