using MaBibli.Shared.Textes;

namespace MaBibli.Tests;

/// <summary>
/// Clé d'œuvre : ce qu'elle réunit, et surtout <b>ce qu'elle rate</b>.
/// </summary>
/// <remarks>
/// Les cas d'échec sont testés au même titre que les réussites : ils documentent la limite du
/// rapprochement, que l'interface annonce à l'utilisateur. Si l'un d'eux se met à passer un
/// jour, c'est que la règle a changé — et le message affiché doit changer avec.
/// </remarks>
public class CleOeuvreTests
{
    [Theory]
    // Les trois formes rencontrées pour un même roman de Werber.
    [InlineData("Les thanatonautes", "Les thanatonautes : roman")]
    [InlineData("Les thanatonautes", "Les thanatonautes / Bernard Werber")]
    [InlineData("Les thanatonautes : roman", "Les thanatonautes / Bernard Werber")]
    // Casse et accents, comme partout ailleurs dans le projet.
    [InlineData("Germinal", "GERMINAL")]
    public void Reunit_les_variantes_d_un_meme_titre(string a, string b) =>
        Assert.Equal(CleOeuvre.Cle(a), CleOeuvre.Cle(b));

    [Theory]
    [InlineData("Germinal", "La bête humaine")]
    // Un tome n'est pas rapproché de l'œuvre entière : le point n'est pas coupé.
    [InlineData("Troisième humanité", "Troisième humanité. Tome 1")]
    public void Distingue_deux_oeuvres_differentes(string a, string b) =>
        Assert.NotEqual(CleOeuvre.Cle(a), CleOeuvre.Cle(b));

    /// <summary>
    /// Limite assumée : deux œuvres distinctes partageant leur titre principal se confondent.
    /// Le risque est borné, la comparaison n'ayant lieu qu'à auteur donné.
    /// </summary>
    [Fact]
    public void Confond_deux_oeuvres_partageant_le_titre_principal() =>
        Assert.Equal(
            CleOeuvre.Cle("Nouvelles : premier recueil"),
            CleOeuvre.Cle("Nouvelles : second recueil"));

    /// <summary>
    /// Limite <b>héritée</b> de <see cref="NormalisationTexte"/>, pas propre à la clé d'œuvre :
    /// la ligature « œ » n'est pas ramenée à « oe ».
    /// </summary>
    /// <remarks>
    /// <c>NormalisationTexte</c> décompose en NFD, qui sépare les accents mais laisse les
    /// ligatures intactes — seul NFKD les défait. Conséquence concrète : <i>L'Œuvre</i> de Zola,
    /// que la BnF écrit avec la ligature, n'est pas rapproché d'un « L'oeuvre » saisi au clavier.
    /// <para>
    /// Le défaut ne vient pas d'ici et ne se corrige pas ici : la même fonction alimente la
    /// recherche du catalogue et la clé unique des auteurs, et en changer déplacerait ces deux
    /// invariants. Consigné dans IDEES.md ; ce test existe pour que la limite soit visible plutôt
    /// que découverte en usage.
    /// </para>
    /// </remarks>
    [Fact]
    public void Ne_reduit_pas_la_ligature_oe() =>
        Assert.NotEqual(CleOeuvre.Cle("L'Œuvre"), CleOeuvre.Cle("L'oeuvre"));

    /// <summary>
    /// Limite assumée : un titre retraduit n'est pas rapproché du tout.
    /// </summary>
    [Fact]
    public void Ne_rapproche_pas_un_titre_retraduit() =>
        Assert.NotEqual(CleOeuvre.Cle("Le Seigneur des anneaux"), CleOeuvre.Cle("The Lord of the Rings"));

    [Theory]
    [InlineData(null)]
    [InlineData("")]
    [InlineData("   ")]
    public void Rend_une_cle_vide_pour_une_saisie_vide(string? titre) =>
        Assert.Equal(string.Empty, CleOeuvre.Cle(titre));

    /// <summary>
    /// Un titre réduit à son seul sous-titre ne doit pas produire une clé vide : elle se
    /// confondrait avec toutes les autres clés vides.
    /// </summary>
    [Fact]
    public void Ne_vide_pas_un_titre_qui_commence_par_le_separateur() =>
        Assert.NotEqual(string.Empty, CleOeuvre.Cle(": roman"));
}
