using MaBibli.Shared.Textes;

namespace MaBibli.Shared.Entites;

/// <summary>
/// Un auteur du catalogue. Table dédiée, et non plus un champ texte sur <see cref="Livre"/>.
/// </summary>
/// <remarks>
/// Deux besoins imposaient la table : regrouper les livres d'un même auteur d'un clic, et
/// retrouver « Émile » en tapant « Emile ». Un champ texte libre ne sait faire ni l'un ni l'autre.
/// </remarks>
public class Auteur
{
    public int Id { get; set; }

    /// <summary>Nom tel qu'affiché, accents et casse compris : « Émile Zola ».</summary>
    public string Nom { get; set; } = string.Empty;

    /// <summary>
    /// Forme normalisée du nom (minuscules, sans accents), dans l'ordre de saisie.
    /// Sert à la <b>recherche</b>.
    /// </summary>
    public string NomNormalise { get; set; } = string.Empty;

    /// <summary>
    /// Clé de regroupement : mêmes mots normalisés mais <b>triés</b>, ce qui rend l'ordre
    /// indifférent. <b>Unique</b> en base : c'est elle qui empêche « Zola, Émile » et
    /// « Émile Zola » de coexister.
    /// </summary>
    public string CleRegroupement { get; set; } = string.Empty;

    public List<LivreAuteur> Livres { get; set; } = [];

    /// <summary>Renseigne les deux formes dérivées à partir du nom d'affichage.</summary>
    public void RecalculerFormes()
    {
        Nom = Nom.Trim();
        NomNormalise = NormalisationTexte.Normaliser(Nom);
        CleRegroupement = RapprochementAuteurs.Cle(Nom);
    }
}

/// <summary>
/// Table de liaison livre ↔ auteur : un livre peut avoir plusieurs auteurs.
/// </summary>
/// <remarks>
/// Le cas n'est pas théorique : le lookup ISBN d'<i>Introduction to Algorithms</i> renvoie
/// quatre noms (Cormen, Leiserson, Rivest, Stein). <see cref="Position"/> conserve l'ordre de
/// la couverture, qui n'est pas alphabétique et fait partie de l'information.
/// </remarks>
public class LivreAuteur
{
    public int LivreId { get; set; }

    public Livre? Livre { get; set; }

    public int AuteurId { get; set; }

    public Auteur? Auteur { get; set; }

    /// <summary>Rang de l'auteur sur la couverture, à partir de 0.</summary>
    public int Position { get; set; }
}

/// <summary>
/// Rapprochement d'auteurs <b>explicitement refusé</b> par l'utilisateur.
/// </summary>
/// <remarks>
/// Sans cette mémoire, une suggestion écartée reviendrait à chaque affichage : « Hamilton » et
/// « Peter F. Hamilton » se ressembleront toujours autant. On ne stocke <b>que</b> les refus ;
/// les suggestions elles-mêmes sont recalculées à la demande, et une acceptation ne laisse rien
/// à mémoriser puisque l'un des deux auteurs disparaît.
/// <para>
/// Le couple est toujours rangé avec le plus petit identifiant en premier, pour qu'un refus vaille
/// dans les deux sens.
/// </para>
/// </remarks>
public class RapprochementRefuse
{
    public int Id { get; set; }

    public int AuteurAId { get; set; }

    public int AuteurBId { get; set; }
}
