@using MaBibli.Shared.Dtos

<li class="carte-serie arbre-serie" @key="Serie.Id">
    <div class="arbre-serie-entete">
        <button type="button" class="bouton bouton-discret"
                aria-expanded="@Deplie"
                @onclick="Basculer">
            @(Deplie ? "▼" : "▶")
        </button>
        <a class="carte-titre" href="@($"series/{Serie.Id}")">@Serie.Titre</a>
        <span class="carte-details">@Avancement()</span>
        @if (ActionsActives)
        {
            <button type="button" class="bouton bouton-compact"
                    disabled="@(_index == 0)" title="@MotifBlocage"
                    aria-label="@($"Monter « {Serie.Titre} »")"
                    @onclick="Monter">▲</button>
            <button type="button" class="bouton bouton-compact"
                    disabled="@(_index < 0 || _index == Soeurs.Count - 1)" title="@MotifBlocage"
                    aria-label="@($"Descendre « {Serie.Titre} »")"
                    @onclick="Descendre">▼</button>
        }
    </div>

    @if (Deplie)
    {
        <div class="arbre-serie-detail">
            @if (Serie.Elements.Count == 0)
            {
                <p class="message-discret">Aucun tome recensé.</p>
            }
            else
            {
                @foreach (var element in Serie.Elements)
                {
                    @if (element.LivreId is { } livreId
                         && Livres.FirstOrDefault(l => l.Id == livreId) is { } livre)
                    {
                        <CarteLivre Livre="livre" />
                    }
                    else
                    {
                        <p class="carte-tome tome-manquant">
                            @element.Titre
                            <span class="etiquette etiquette-manquant">Pas dans la bibliothèque</span>
                        </p>
                    }
                }
            }

            @if (Enfants.Count > 0)
            {
                <ul class="liste-sous-series">
                    @foreach (var enfant in Enfants.Where(e => !CheminAvecSerie.Contains(e.Id)))
                    {
                        <ArbreSerie Serie="enfant" Toutes="Toutes" Livres="Livres"
                                    Totaux="Totaux" Chemin="@CheminAvecSerie"
                                    ActionsActives="ActionsActives"
                                    MotifBlocage="MotifBlocage"
                                    Deplies="Deplies"
                                    OnDeplacer="OnDeplacer" />
                    }
                </ul>
            }
        </div>
    }
</li>

@code {
    [Parameter, EditorRequired] public SerieDto Serie { get; set; } = default!;
    [Parameter, EditorRequired] public IReadOnlyList<SerieDto> Toutes { get; set; } = [];
    [Parameter, EditorRequired] public IReadOnlyList<LivreDto> Livres { get; set; } = [];
    [Parameter, EditorRequired] public IReadOnlyDictionary<int, (int Possedes, int Total)> Totaux { get; set; } = new Dictionary<int, (int, int)>();
    [Parameter] public IReadOnlySet<int> Chemin { get; set; } = new HashSet<int>();
    [Parameter] public ISet<int> Deplies { get; set; } = new HashSet<int>();
    [Parameter] public bool ActionsActives { get; set; }
    [Parameter] public string? MotifBlocage { get; set; }
    [Parameter] public EventCallback<DeplacementSerie> OnDeplacer { get; set; }

    private List<SerieDto> Soeurs => Toutes
        .Where(s => s.SerieParenteId == Serie.SerieParenteId)
        .OrderBy(s => s.Position)
        .ThenBy(s => s.Id)
        .ToList();

    private List<SerieDto> Enfants => Toutes
        .Where(s => s.SerieParenteId == Serie.Id)
        .OrderBy(s => s.Position)
        .ThenBy(s => s.Id)
        .ToList();

    private int _index => Soeurs.FindIndex(s => s.Id == Serie.Id);
    private bool Deplie => Deplies.Contains(Serie.Id);
    private IReadOnlySet<int> CheminAvecSerie => new HashSet<int>(Chemin) { Serie.Id };

    private string Avancement()
    {
        var total = Totaux.TryGetValue(Serie.Id, out var valeur)
            ? valeur
            : (Possedes: Serie.NombrePossedes, Total: Serie.Elements.Count);
        return total.Total == 0
            ? "Aucun tome recensé"
            : $"{total.Possedes} sur {total.Total} tome{(total.Total > 1 ? "s" : "")}";
    }

    private void Basculer()
    {
        if (!Deplies.Add(Serie.Id))
        {
            Deplies.Remove(Serie.Id);
        }
    }

    private Task Monter() => Deplacer(-1);
    private Task Descendre() => Deplacer(1);

    private Task Deplacer(int delta) =>
        Serie.SerieParenteId is { } parent
            ? OnDeplacer.InvokeAsync(new DeplacementSerie(Serie.Id, parent, delta))
            : Task.CompletedTask;
}
