using MaBibli.Shared.Isbn;

namespace MaBibli.Tests;

/// <summary>
/// Découpage des ISBN pour l'affichage.
/// </summary>
/// <remarks>
/// Les valeurs attendues ci-dessous ne sont pas devinées : elles ont été calculées à partir du
/// <c>RangeMessage.xml</c> officiel de l'agence internationale (version du 2026-08-18), qui est
/// aussi la source des tables embarquées.
/// </remarks>
public class FormatageIsbnTests
{
    /// <summary>
    /// Le fonds francophone est découpé <b>en entier</b>, éditeur compris.
    /// </summary>
    [Theory]
    [InlineData("9782846391009", "978-2-84639-100-9")]  // le cas remonté en usage
    [InlineData("9782070612758", "978-2-07-061275-8")]  // Gallimard : éditeur sur 2 chiffres
    [InlineData("9782253004226", "978-2-253-00422-6")]  // Livre de poche : 3 chiffres
    [InlineData("9782080704092", "978-2-08-070409-2")]  // Flammarion : 2 chiffres
    public void Decoupe_entierement_le_francophone(string nu, string attendu)
        => Assert.Equal(attendu, FormatageIsbn.Afficher(nu));

    /// <summary>
    /// Un ISBN-10 est un ISBN-13 en <c>978</c> amputé de son préfixe : mêmes tranches,
    /// une frontière de moins.
    /// </summary>
    [Theory]
    [InlineData("2253004227", "2-253-00422-7")]
    [InlineData("2080704095", "2-08-070409-5")]
    public void Decoupe_aussi_les_ISBN10(string nu, string attendu)
        => Assert.Equal(attendu, FormatageIsbn.Afficher(nu));

    /// <summary>
    /// Hors du francophone, on s'arrête au groupe et à la clé : <b>deux frontières toujours
    /// exactes</b>. Le vrai découpage est <c>978-0-262-03384-8</c> — on ne l'invente pas, on
    /// affiche une tranche de moins. Une coupure absente se lit encore, une coupure fausse trompe.
    /// </summary>
    [Theory]
    [InlineData("9780262033848", "978-0-26203384-8")]
    [InlineData("0262033844", "0-26203384-4")]
    public void Ne_devine_pas_lediteur_hors_du_francophone(string nu, string attendu)
        => Assert.Equal(attendu, FormatageIsbn.Afficher(nu));

    /// <summary>
    /// Ce qui n'est pas un ISBN valide ressort <b>tel quel</b> : un code mal saisi doit se voir
    /// mal saisi, pas déguisé en ISBN par des tirets.
    /// </summary>
    [Theory]
    [InlineData("9782846391008")]      // clé fausse
    [InlineData("978284639100")]       // trop court
    [InlineData("9772466671438")]      // périodique : préfixe 977, aucun ISBN à découper
    [InlineData("pas un isbn")]
    public void Laisse_intact_ce_qui_nest_pas_un_ISBN(string brut)
        => Assert.Equal(brut, FormatageIsbn.Afficher(brut));

    [Theory]
    [InlineData(null)]
    [InlineData("")]
    [InlineData("   ")]
    public void Vide_reste_vide(string? brut)
        => Assert.Equal(string.Empty, FormatageIsbn.Afficher(brut));

    /// <summary>
    /// Un ISBN déjà découpé — recopié d'une page web, par exemple — se redécoupe à l'identique
    /// plutôt que de cumuler les tirets.
    /// </summary>
    [Fact]
    public void Est_idempotent()
    {
        var une = FormatageIsbn.Afficher("9782846391009");
        Assert.Equal(une, FormatageIsbn.Afficher(une));
    }

    /// <summary>
    /// ⚠️ Le contrat central : la valeur <b>stockée</b> reste nue. Ces tirets sont un habillage,
    /// et la BnF indexe l'ISBN sans eux — les laisser filer dans une requête casserait le lookup.
    /// </summary>
    [Fact]
    public void Le_decoupage_se_defait_par_Normaliser()
        => Assert.Equal(
            "9782846391009",
            IsbnUtils.Normaliser(FormatageIsbn.Afficher("9782846391009")));
}
