using MaBibli.Api.Services.Identite;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;

namespace MaBibli.Tests;

/// <summary>
/// Lecture de l'identité dans les en-têtes SSOwat, et repli sur l'utilisateur simulé
/// en développement.
/// </summary>
public class FournisseurUtilisateurTests
{
    private static FournisseurUtilisateurSsowat Construire(
        IDictionary<string, string>? entetes = null,
        OptionsIdentite? options = null)
    {
        var contexte = new DefaultHttpContext();
        foreach (var (nom, valeur) in entetes ?? new Dictionary<string, string>())
        {
            contexte.Request.Headers[nom] = valeur;
        }

        var accesseur = new HttpContextAccessor { HttpContext = contexte };
        return new FournisseurUtilisateurSsowat(accesseur, Options.Create(options ?? new OptionsIdentite()));
    }

    [Fact]
    public void Les_entetes_ssowat_sont_lus()
    {
        var fournisseur = Construire(new Dictionary<string, string>
        {
            ["YNH_USER"] = "mathieu",
            ["YNH_USER_EMAIL"] = "mathieu@example.org",
            ["YNH_USER_FULLNAME"] = "Mathieu L.",
        });

        var utilisateur = fournisseur.Obtenir();

        Assert.Equal("mathieu", utilisateur.Identifiant);
        Assert.Equal("mathieu@example.org", utilisateur.Email);
        Assert.Equal("Mathieu L.", utilisateur.NomComplet);
        Assert.False(utilisateur.Simule);
        Assert.Equal("Mathieu L.", utilisateur.Affichage);
    }

    [Fact]
    public void Lentete_utilisateur_seul_suffit()
    {
        var utilisateur = Construire(new Dictionary<string, string> { ["YNH_USER"] = "camille" }).Obtenir();

        Assert.Equal("camille", utilisateur.Identifiant);
        Assert.Null(utilisateur.Email);
        Assert.Equal("camille", utilisateur.Affichage);
    }

    [Fact]
    public void Lentete_ssowat_prime_sur_lutilisateur_simule()
    {
        // Sur le serveur, une configuration de dev oubliée ne doit jamais masquer l'identité réelle.
        var fournisseur = Construire(
            new Dictionary<string, string> { ["YNH_USER"] = "camille" },
            new OptionsIdentite { UtilisateurSimule = "dev" });

        var utilisateur = fournisseur.Obtenir();

        Assert.Equal("camille", utilisateur.Identifiant);
        Assert.False(utilisateur.Simule);
    }

    [Fact]
    public void Sans_entete_lutilisateur_simule_prend_le_relais()
    {
        var fournisseur = Construire(options: new OptionsIdentite
        {
            UtilisateurSimule = "dev",
            EmailSimule = "dev@localhost",
            NomCompletSimule = "Utilisateur de développement",
        });

        var utilisateur = fournisseur.Obtenir();

        Assert.Equal("dev", utilisateur.Identifiant);
        Assert.Equal("Utilisateur de développement", utilisateur.NomComplet);
        Assert.True(utilisateur.Simule);
    }

    [Fact]
    public void Sans_entete_ni_simulation_lidentite_reste_inconnue()
    {
        // On n'invente pas d'identité : mieux vaut un livre sans traçabilité qu'un faux nom.
        var utilisateur = Construire().Obtenir();

        Assert.Null(utilisateur.Identifiant);
        Assert.False(utilisateur.Simule);
        Assert.Equal("inconnu", utilisateur.Affichage);
    }

    [Fact]
    public void Un_entete_vide_est_traite_comme_absent()
    {
        var fournisseur = Construire(
            new Dictionary<string, string> { ["YNH_USER"] = "   " },
            new OptionsIdentite { UtilisateurSimule = "dev" });

        var utilisateur = fournisseur.Obtenir();

        Assert.Equal("dev", utilisateur.Identifiant);
        Assert.True(utilisateur.Simule);
    }
}
