using MaBibli.Shared.Dtos;
using MaBibli.Shared.Isbn;
namespace MaBibli.Api.Services.Isbn;
public interface IIsbnLookupService
{
///
/// Cherche toutes les notices correspondant à un ISBN.
///
/// null si l'ISBN fourni n'est pas un ISBN valide.
Task RechercherAsync(string isbnBrut, CancellationToken ct = default);
}
///
/// Cascade de lookup ISBN : BnF d'abord, OpenLibrary ensuite.
///
///
/// L'ordre est dicté par CLAUDE.md : la collection est majoritairement francophone et le dépôt
/// légal français donne à la BnF la meilleure couverture possible sur ce fonds, là où OpenLibrary
/// est lacunaire. OpenLibrary n'est interrogée que si la BnF ne renvoie rien sous
/// aucune des deux formes d'ISBN.
///
public sealed class IsbnLookupService(
IBnfClient bnf,
IOpenLibraryClient openLibrary,
ILogger logger) : IIsbnLookupService
{
public async Task RechercherAsync(string isbnBrut, CancellationToken ct = default)
{
var isbn = IsbnUtils.Normaliser(isbnBrut);
if (!IsbnUtils.EstValide(isbn))
{
return null;
}
// La couverture ne vient jamais de la BnF : son Dublin Core n'en fournit aucune.
// On construit l'URL OpenLibrary quelle que soit la source des métadonnées.
var couverture = IsbnUtils.UrlCouverture(isbn!);
IsbnUtils.TryConvertirEnIsbn10(isbn, out var isbn10);
var avertissements = new List();
// 1. BnF avec l'ISBN tel que scanné.
var (candidats, avertissement) = await bnf.RechercherAsync(isbn!, couverture, ct);
Ajouter(avertissements, avertissement);
// 2. BnF avec l'ISBN-10 converti. Indispensable : la BnF indexe l'ISBN tel qu'imprimé,
// et les ouvrages d'avant 2007 ne portent qu'un ISBN-10.
if (candidats.Count == 0 && isbn10 is not null)
{
var (candidats10, avertissement10) = await bnf.RechercherAsync(isbn10, couverture, ct);
Ajouter(avertissements, avertissement10);
candidats = candidats10;
}
// 3. OpenLibrary en second rideau, seulement si la BnF n'a rien donné du tout.
if (candidats.Count == 0)
{
var (candidatsOl, avertissementOl) = await openLibrary.RechercherAsync(isbn!, couverture, ct);
Ajouter(avertissements, avertissementOl);
candidats = candidatsOl;
}
logger.LogInformation(
"Lookup ISBN {Isbn} : {Nombre} candidat(s), {Avertissements} avertissement(s)",
isbn, candidats.Count, avertissements.Count);
return new ResultatLookupIsbn
{
IsbnDemande = isbn!,
Isbn10 = isbn10,
Candidats = candidats,
Avertissements = avertissements,
};
}
private static void Ajouter(List avertissements, string? message)
{
if (!string.IsNullOrEmpty(message))
{
avertissements.Add(message);
}
}
}