@*
    Formulaire d'une fiche livre, partagé par l'ajout (ISBN ou manuel) et l'édition.

    Le pré-remplissage par ISBN est une AIDE, pas une contrainte : tous les champs restent
    modifiables, et une fiche incomplète peut toujours être complétée à la main (CLAUDE.md).
*@
<div class="formulaire">
    @if (!string.IsNullOrEmpty(Saisie.CoverUrl) || !string.IsNullOrWhiteSpace(Saisie.Titre))
    {
        <div class="formulaire-apercu">
            <Couverture Url="@Saisie.CoverUrl" Titre="@Saisie.Titre" Classe="couverture-moyenne" />
        </div>
    }

    <label class="champ">
        <span class="champ-libelle">Titre <span class="obligatoire" aria-hidden="true">*</span></span>
        <input class="champ-saisie" type="text" @bind="Saisie.Titre" @bind:event="oninput"
               placeholder="Titre du livre" autocomplete="off" />
    </label>

    @*
        Un seul champ, plusieurs auteurs : le point-virgule les sépare. La virgule est déjà
        prise par la forme bibliographique « Zola, Émile », qu'on doit pouvoir taper telle quelle.
        Le serveur rapproche ensuite les variantes sûres d'un auteur déjà connu.
    *@
    <label class="champ">
        <span class="champ-libelle">
            Auteur<span class="champ-aide"> (plusieurs : séparez par « ; »)</span>
        </span>
        <input class="champ-saisie" type="text" @bind="Saisie.Auteur" @bind:event="oninput"
               placeholder="Prénom Nom ; Prénom Nom" autocomplete="off" />
    </label>

    @*
        Les rôles n'apparaissent qu'à partir de DEUX auteurs, et c'est délibéré : un roman n'a
        qu'un signataire dont le rôle ne se pose pas, et une ligne de boutons sous chaque saisie
        n'apprendrait rien. La question « qui écrit, qui dessine ? » ne se pose qu'à plusieurs.
        Le défaut reste « non précisé » : on ne remplit pas une case à la place de l'utilisateur.
    *@
    @if (Saisie.Auteurs.Count > 1)
    {
        <fieldset class="champ">
            <legend class="champ-libelle">
                Rôles<span class="champ-aide"> (facultatif — utile pour une BD)</span>
            </legend>

            @foreach (var (auteur, index) in Saisie.Auteurs.Select((a, i) => (a, i)))
            {
                <div class="ligne-role" @key="index">
                    <span class="nom-role">@auteur.Nom</span>
                    <div class="segments">
                        @foreach (var role in Roles)
                        {
                            <button type="button"
                                    class="segment @(auteur.Role == role ? "segment-actif" : null)"
                                    @onclick="() => PoserRole(index, role)">
                                @Libelles.RoleAuteur(role)
                            </button>
                        }
                    </div>
                </div>
            }
        </fieldset>
    }

    <label class="champ">
        <span class="champ-libelle">Éditeur</span>
        <input class="champ-saisie" type="text" @bind="Saisie.Editeur" @bind:event="oninput"
               autocomplete="off" />
    </label>

    <label class="champ">
        @* Point-virgule, comme le champ des auteurs juste au-dessus : trois champs voisins du
           même formulaire ne doivent pas se saisir de trois façons. La virgule reste acceptée —
           un thème n'en contient jamais, contrairement à un titre d'article à la une. *@
        <span class="champ-libelle">
            Thèmes <span class="champ-aide">(séparés par des points-virgules)</span>
        </span>
        <input class="champ-saisie" type="text" @bind="Saisie.ThemesTexte" @bind:event="oninput"
               placeholder="Fantasy ; aventure ; space opera" autocomplete="off" />
    </label>

    <label class="champ">
        <span class="champ-libelle">ISBN <span class="champ-aide">(facultatif)</span></span>
        <input class="champ-saisie" type="text" inputmode="numeric" @bind="Saisie.Isbn" @bind:event="oninput"
               placeholder="978…" autocomplete="off" />
    </label>

    @*
        Le format n'est plus affiché dans les listes que pour les ebooks : un livre y est donc
        physique par défaut. Cette valeur DOIT rester présélectionnée ici, sinon on créerait
        des fiches sans format en croyant que « rien d'affiché = physique ».
        C'est le cas sans code particulier : Format.Physique vaut 0, valeur par défaut de
        l'énumération, et le segment correspondant est donc actif dès l'ouverture.
    *@
    <fieldset class="champ">
        <legend class="champ-libelle">
            Format<span class="champ-aide"> (physique par défaut)</span>
        </legend>
        <div class="segments">
            @foreach (var format in Formats)
            {
                <button type="button"
                        class="segment @(Saisie.Format == format ? "segment-actif" : null)"
                        @onclick="() => Saisie.Format = format">
                    @Libelles.Format(format)
                </button>
            }
        </div>
    </fieldset>

    @*
        ⚠️ Le défaut est « non précisé », PAS « roman » : on ne remplit pas une case à la place
        de l'utilisateur. C'est aussi ce qui rend l'étiquette honnête dans les listes — elle ne
        s'affiche que lorsqu'un type a été choisi.
    *@
    <fieldset class="champ">
        <legend class="champ-libelle">
            Type<span class="champ-aide"> (facultatif)</span>
        </legend>
        <div class="segments">
            @foreach (var type in Types)
            {
                <button type="button"
                        class="segment @Libelles.ClasseTypeDocument(type) @(Saisie.TypeDocument == type ? "segment-actif" : null)"
                        @onclick="() => Saisie.TypeDocument = type">
                    @Libelles.TypeDocument(type)
                </button>
            }
        </div>
    </fieldset>

    <fieldset class="champ">
        <legend class="champ-libelle">
            Statut de lecture<span class="champ-aide"> (le vôtre)</span>
        </legend>
        <ChoixStatut Valeur="Saisie.Statut" ValeurChanged="s => Saisie.Statut = s" />
    </fieldset>

    <label class="champ">
        <span class="champ-libelle">URL de couverture</span>
        <input class="champ-saisie" type="url" @bind="Saisie.CoverUrl" @bind:event="oninput"
               placeholder="https://…" autocomplete="off" />
    </label>

    @if (!string.IsNullOrEmpty(Erreur))
    {
        <p class="message-erreur" role="alert">@Erreur</p>
    }

    @* Un enregistrement impossible se dit AVANT le clic : un bouton qui échoue en silence est
       pire que pas de bouton du tout (CLAUDE.md, stratégie hors-ligne). *@
    @if (!string.IsNullOrEmpty(MessageBlocage))
    {
        <p class="message-avertissement" role="status">@MessageBlocage</p>
    }

    <div class="actions-formulaire">
        <button type="button" class="bouton bouton-principal"
                disabled="@(EnCours || Bloque || string.IsNullOrWhiteSpace(Saisie.Titre))"
                title="@MessageBlocage"
                @onclick="Valider">
            @(EnCours ? "Enregistrement…" : LibelleValidation)
        </button>

        @if (OnAnnuler.HasDelegate)
        {
            <button type="button" class="bouton bouton-discret" disabled="@EnCours"
                    @onclick="OnAnnuler">
                Annuler
            </button>
        }
    </div>
</div>

@code {
    private static readonly Format[] Formats = Enum.GetValues<Format>();

    private static readonly TypeDocument[] Types = Enum.GetValues<TypeDocument>();

    private static readonly RoleAuteur[] Roles = Enum.GetValues<RoleAuteur>();

    /// <summary>
    /// Pose le rôle d'un auteur.
    /// </summary>
    /// <remarks>
    /// <see cref="AuteurSaisi"/> est un record : on remplace l'entrée plutôt que de la muter,
    /// et la liste reste celle que la propriété <c>Auteur</c> saura relire pour préserver les
    /// rôles à la frappe suivante.
    /// </remarks>
    private void PoserRole(int index, RoleAuteur role) =>
        Saisie.Auteurs[index] = Saisie.Auteurs[index] with { Role = role };

    [Parameter, EditorRequired] public EnregistrementLivre Saisie { get; set; } = new();

    [Parameter] public string LibelleValidation { get; set; } = "Enregistrer";

    [Parameter] public string? Erreur { get; set; }

    [Parameter] public bool EnCours { get; set; }

    /// <summary>
    /// Raison pour laquelle l'enregistrement est impossible (typiquement l'absence de réseau).
    /// Renseignée, elle désactive la validation et s'affiche : la saisie reste lisible, mais
    /// l'utilisateur sait pourquoi il ne peut pas valider.
    /// </summary>
    [Parameter] public string? MessageBlocage { get; set; }

    private bool Bloque => !string.IsNullOrEmpty(MessageBlocage);

    [Parameter] public EventCallback OnValider { get; set; }

    [Parameter] public EventCallback OnAnnuler { get; set; }

    private Task Valider() => OnValider.InvokeAsync();
}
