@page "/administration"
@page "/administration.html"
@using System.ComponentModel.DataAnnotations
@using System.Net
@using System.Net.Http.Json
@using ChessCubing.App.Models.Users
@implements IDisposable
@inject AuthenticationStateProvider AuthenticationStateProvider
@inject HttpClient Http

<PageTitle>ChessCubing Arena | Administration</PageTitle>
<PageBody BodyClass="home-body" />

<div class="ambient ambient-left"></div>
<div class="ambient ambient-right"></div>

<div class="rules-shell">
    <header class="hero hero-home user-hero">
        <div class="hero-copy">
            <p class="eyebrow">Administration</p>
            <h1>Gerer les utilisateurs avec une vue tableau</h1>
            <p class="lead">
                Cette zone rassemble les comptes Keycloak et les profils du site
                dans une interface plus classique, avec ajout, edition et suppression.
            </p>
            <div class="hero-actions">
                <a class="button secondary" href="utilisateur.html">Voir l'espace utilisateur</a>
                <a class="button ghost" href="index.html">Retour au site</a>
            </div>
        </div>

        <aside class="hero-preview">
            <div class="preview-card">
                <p class="micro-label">Vue d'ensemble</p>
                <div class="home-mini-grid two-columns admin-hero-stats">
                    <article class="mini-panel">
                        <span class="micro-label">Comptes</span>
                        <strong>@Users.Count</strong>
                    </article>
                    <article class="mini-panel">
                        <span class="micro-label">Profils site</span>
                        <strong>@Users.Count(user => user.HasSiteProfile)</strong>
                    </article>
                    <article class="mini-panel">
                        <span class="micro-label">Actifs</span>
                        <strong>@Users.Count(user => user.IsEnabled)</strong>
                    </article>
                    <article class="mini-panel">
                        <span class="micro-label">Emails verifies</span>
                        <strong>@Users.Count(user => user.IsEmailVerified)</strong>
                    </article>
                </div>
            </div>

            <div class="preview-banner">
                <span class="mini-chip">Etat d'acces</span>
                <strong>@HeroStatusTitle</strong>
                <p>@HeroStatusDescription</p>
            </div>
        </aside>
    </header>

    <main class="rules-grid">
        @if (!IsAuthenticated)
        {
            <section class="panel panel-wide cta-panel">
                <div class="section-heading">
                    <div>
                        <p class="eyebrow">Connexion requise</p>
                        <h2>Connecte-toi avec un compte administrateur</h2>
                    </div>
                    <p class="section-copy">
                        La gestion des utilisateurs devient disponible des qu'un compte
                        portant le role `admin` est connecte.
                    </p>
                </div>
            </section>
        }
        else if (!IsAdmin)
        {
            <section class="panel panel-wide">
                <div class="section-heading">
                    <div>
                        <p class="eyebrow">Acces refuse</p>
                        <h2>Ce compte n'a pas les droits d'administration</h2>
                    </div>
                    <p class="section-copy">
                        La gestion des utilisateurs est reservee aux comptes portant le role `admin`.
                    </p>
                </div>
            </section>
        }
        else if (IsLoadingUsers)
        {
            <section class="panel panel-wide">
                <p class="eyebrow">Chargement</p>
                <h2>Recuperation de la liste des utilisateurs</h2>
                <p class="section-copy">Le site rassemble les comptes Keycloak et les profils du site.</p>
            </section>
        }
        else if (!string.IsNullOrWhiteSpace(LoadError))
        {
            <section class="panel panel-wide">
                <p class="eyebrow">Serveur</p>
                <h2>Impossible de charger l'administration</h2>
                <p class="profile-feedback error">@LoadError</p>
                <div class="hero-actions">
                    <button class="button secondary" type="button" @onclick="ReloadUsersAsync">Reessayer</button>
                </div>
            </section>
        }
        else
        {
            <section class="panel panel-wide admin-table-panel">
                <div class="section-heading">
                    <div>
                        <p class="eyebrow">Utilisateurs</p>
                        <h2>Liste des comptes</h2>
                    </div>
                    <p class="section-copy">
                        Le tableau centralise les comptes du site avec une colonne d'actions
                        pour les operations courantes.
                    </p>
                </div>

                @if (!string.IsNullOrWhiteSpace(SaveError))
                {
                    <p class="profile-feedback error">@SaveError</p>
                }

                @if (!string.IsNullOrWhiteSpace(SaveMessage))
                {
                    <p class="profile-feedback success">@SaveMessage</p>
                }

                <div class="admin-toolbar admin-toolbar-grid">
                    <label class="field admin-search-field">
                        <span>Recherche</span>
                        <input @bind="SearchTerm" @bind:event="oninput" placeholder="Nom, email, club, ville..." />
                    </label>

                    <div class="admin-toolbar-actions">
                        <button class="button secondary small with-icon" type="button" @onclick="OpenCreateModal">
                            <span class="material-icons action-icon" aria-hidden="true">person_add</span>
                            <span>Ajouter un utilisateur</span>
                        </button>
                        <button class="button ghost small with-icon" type="button" @onclick="ReloadUsersAsync" disabled="@IsLoadingUsers">
                            <span class="material-icons action-icon" aria-hidden="true">refresh</span>
                            <span>Actualiser</span>
                        </button>
                    </div>
                </div>

                @if (FilteredUsers.Count == 0)
                {
                    <div class="callout">
                        <span class="micro-label">Recherche</span>
                        <p>Aucun utilisateur ne correspond au filtre en cours.</p>
                    </div>
                }
                else
                {
                    <div class="admin-table-shell">
                        <table class="admin-table">
                            <thead>
                                <tr>
                                    <th>Utilisateur</th>
                                    <th>Email</th>
                                    <th>Nom affiche</th>
                                    <th>Etat</th>
                                    <th>Profil site</th>
                                    <th>Derniere mise a jour</th>
                                    <th>Actions</th>
                                </tr>
                            </thead>
                            <tbody>
                                @foreach (var user in FilteredUsers)
                                {
                                    <tr class="@BuildTableRowClass(user)">
                                        <td>
                                            <div class="admin-cell-stack">
                                                <strong>@user.Username</strong>
                                                <span>@user.IdentityDisplayName</span>
                                            </div>
                                        </td>
                                        <td>@(user.Email ?? "Non renseigne")</td>
                                        <td>@(user.SiteDisplayName ?? "A definir")</td>
                                        <td>
                                            <span class="mini-chip @(user.IsEnabled ? "admin-chip-success" : "admin-chip-danger")">
                                                @(user.IsEnabled ? "Actif" : "Suspendu")
                                            </span>
                                        </td>
                                        <td>
                                            <span class="mini-chip @(user.HasSiteProfile ? "admin-chip-neutral" : "admin-chip-outline")">
                                                @(user.HasSiteProfile ? "Cree" : "Absent")
                                            </span>
                                        </td>
                                        <td>@BuildUserCardFootnote(user)</td>
                                        <td>
                                            <div class="admin-actions-cell">
                                                <button class="button ghost small icon-button"
                                                        type="button"
                                                        title="Modifier"
                                                        aria-label="Modifier"
                                                        @onclick="@(() => SelectUserAsync(user.Subject))">
                                                    <span class="material-icons action-icon" aria-hidden="true">edit</span>
                                                </button>
                                                <button class="button ghost danger small icon-button"
                                                        type="button"
                                                        title="Supprimer"
                                                        aria-label="Supprimer"
                                                        @onclick="@(() => PromptDeleteUser(user))">
                                                    <span class="material-icons action-icon" aria-hidden="true">delete</span>
                                                </button>
                                            </div>
                                        </td>
                                    </tr>
                                }
                            </tbody>
                        </table>
                    </div>
                }
            </section>

        }
    </main>
</div>

<section class="modal @(ShowEditModal ? string.Empty : "hidden")" aria-hidden="@BoolString(!ShowEditModal)">
    <div class="modal-backdrop" @onclick="CloseEditModal"></div>
    <div class="modal-card admin-modal-card">
        <div class="modal-head">
            <div>
                <p class="eyebrow">Edition</p>
                <h2>@BuildEditModalTitle()</h2>
            </div>
            <button class="button ghost small" type="button" @onclick="CloseEditModal" disabled="@IsSaving">Fermer</button>
        </div>

        @if (IsLoadingDetail)
        {
            <p class="section-copy">La fiche utilisateur est en cours de chargement.</p>
        }
        else if (!string.IsNullOrWhiteSpace(DetailError))
        {
            <p class="profile-feedback error">@DetailError</p>
            <div class="modal-actions">
                <button class="button secondary" type="button" @onclick="ReloadSelectedUserAsync">Recharger</button>
                <button class="button ghost" type="button" @onclick="CloseEditModal">Fermer</button>
            </div>
        }
        else if (SelectedUser is null)
        {
            <p class="section-copy">Cette fiche n'est plus disponible pour le moment.</p>
        }
        else
        {
            <p class="section-copy">
                Les roles restent geres dans Keycloak. Cette fiche couvre l'etat du compte et le profil du site.
            </p>

            @if (!string.IsNullOrWhiteSpace(SaveError))
            {
                <p class="profile-feedback error">@SaveError</p>
            }

            @if (!string.IsNullOrWhiteSpace(SaveMessage))
            {
                <p class="profile-feedback success">@SaveMessage</p>
            }

            <div class="profile-meta-grid">
                <article class="profile-meta-card">
                    <span class="micro-label">Identite Keycloak</span>
                    <strong>@SelectedUser.IdentityDisplayName</strong>
                </article>
                <article class="profile-meta-card">
                    <span class="micro-label">Compte cree le</span>
                    <strong>@FormatDate(SelectedUser.AccountCreatedUtc)</strong>
                </article>
                <article class="profile-meta-card">
                    <span class="micro-label">Profil site cree le</span>
                    <strong>@FormatDate(SelectedUser.SiteProfileCreatedUtc)</strong>
                </article>
                <article class="profile-meta-card">
                    <span class="micro-label">Profil site mis a jour</span>
                    <strong>@FormatDate(SelectedUser.SiteProfileUpdatedUtc)</strong>
                </article>
            </div>

            <EditForm Model="@EditFormModel" OnValidSubmit="SaveUserAsync">
                <DataAnnotationsValidator />

                <div class="admin-toggle-grid">
                    <label class="admin-toggle-card">
                        <InputCheckbox @bind-Value="EditFormModel.IsEnabled" />
                        <div>
                            <strong>Compte actif</strong>
                            <span>Autoriser ou bloquer la connexion a l'application.</span>
                        </div>
                    </label>

                    <label class="admin-toggle-card">
                        <InputCheckbox @bind-Value="EditFormModel.IsEmailVerified" />
                        <div>
                            <strong>Email verifie</strong>
                            <span>Indique si l'adresse email a ete validee dans Keycloak.</span>
                        </div>
                    </label>
                </div>

                <div class="admin-form-grid">
                    <label class="field">
                        <span>Nom d'utilisateur</span>
                        <InputText @bind-Value="EditFormModel.Username" />
                        <ValidationMessage For="@(() => EditFormModel.Username)" />
                    </label>

                    <label class="field">
                        <span>Email</span>
                        <InputText @bind-Value="EditFormModel.Email" />
                        <ValidationMessage For="@(() => EditFormModel.Email)" />
                    </label>

                    <label class="field">
                        <span>Prenom</span>
                        <InputText @bind-Value="EditFormModel.FirstName" />
                        <ValidationMessage For="@(() => EditFormModel.FirstName)" />
                    </label>

                    <label class="field">
                        <span>Nom</span>
                        <InputText @bind-Value="EditFormModel.LastName" />
                        <ValidationMessage For="@(() => EditFormModel.LastName)" />
                    </label>

                    <label class="field">
                        <span>Nom affiche sur le site</span>
                        <InputText @bind-Value="EditFormModel.DisplayName" />
                        <ValidationMessage For="@(() => EditFormModel.DisplayName)" />
                    </label>

                    <label class="field">
                        <span>Club</span>
                        <InputText @bind-Value="EditFormModel.Club" />
                        <ValidationMessage For="@(() => EditFormModel.Club)" />
                    </label>

                    <label class="field">
                        <span>Ville</span>
                        <InputText @bind-Value="EditFormModel.City" />
                        <ValidationMessage For="@(() => EditFormModel.City)" />
                    </label>

                    <label class="field">
                        <span>Format prefere</span>
                        <InputSelect @bind-Value="EditFormModel.PreferredFormat">
                            <option value="">Aucune preference</option>
                            <option value="Twice">Twice</option>
                            <option value="Time">Time</option>
                            <option value="Les deux">Les deux</option>
                        </InputSelect>
                        <ValidationMessage For="@(() => EditFormModel.PreferredFormat)" />
                    </label>

                    <label class="field span-2">
                        <span>Cube favori</span>
                        <InputText @bind-Value="EditFormModel.FavoriteCube" />
                        <ValidationMessage For="@(() => EditFormModel.FavoriteCube)" />
                    </label>

                    <label class="field span-2">
                        <span>Bio</span>
                        <InputTextArea @bind-Value="EditFormModel.Bio" />
                        <ValidationMessage For="@(() => EditFormModel.Bio)" />
                    </label>
                </div>

                <div class="profile-actions">
                    <button class="button secondary" type="submit" disabled="@IsSaving">
                        @(IsSaving ? "Enregistrement..." : "Enregistrer les modifications")
                    </button>
                    <button class="button ghost" type="button" @onclick="CloseEditModal" disabled="@IsSaving">Fermer</button>
                    <p class="section-copy">Le profil site est cree automatiquement lors du premier enregistrement.</p>
                </div>
            </EditForm>
        }
    </div>
</section>

<section class="modal @(ShowCreateModal ? string.Empty : "hidden")" aria-hidden="@BoolString(!ShowCreateModal)">
    <div class="modal-backdrop" @onclick="CloseCreateModal"></div>
    <div class="modal-card admin-modal-card">
        <div class="modal-head">
            <div>
                <p class="eyebrow">Ajout</p>
                <h2>Ajouter un utilisateur</h2>
            </div>
            <button class="button ghost small" type="button" @onclick="CloseCreateModal" disabled="@IsCreating">Fermer</button>
        </div>

        <p class="section-copy">
            La creation ajoute un compte dans Keycloak puis initialise le profil du site.
        </p>

        @if (!string.IsNullOrWhiteSpace(CreateError))
        {
            <p class="profile-feedback error">@CreateError</p>
        }

        <EditForm Model="@CreateFormModel" OnValidSubmit="CreateUserAsync">
            <DataAnnotationsValidator />

            <div class="admin-form-grid">
                <label class="field">
                    <span>Nom d'utilisateur</span>
                    <InputText @bind-Value="CreateFormModel.Username" />
                    <ValidationMessage For="@(() => CreateFormModel.Username)" />
                </label>

                <label class="field">
                    <span>Email</span>
                    <InputText @bind-Value="CreateFormModel.Email" />
                    <ValidationMessage For="@(() => CreateFormModel.Email)" />
                </label>

                <label class="field">
                    <span>Prenom</span>
                    <InputText @bind-Value="CreateFormModel.FirstName" />
                    <ValidationMessage For="@(() => CreateFormModel.FirstName)" />
                </label>

                <label class="field">
                    <span>Nom</span>
                    <InputText @bind-Value="CreateFormModel.LastName" />
                    <ValidationMessage For="@(() => CreateFormModel.LastName)" />
                </label>

                <label class="field">
                    <span>Mot de passe</span>
                    <InputText @bind-Value="CreateFormModel.Password" type="password" />
                    <ValidationMessage For="@(() => CreateFormModel.Password)" />
                </label>

                <label class="field">
                    <span>Confirmation du mot de passe</span>
                    <InputText @bind-Value="CreateFormModel.ConfirmPassword" type="password" />
                    <ValidationMessage For="@(() => CreateFormModel.ConfirmPassword)" />
                </label>

                <label class="field">
                    <span>Nom affiche sur le site</span>
                    <InputText @bind-Value="CreateFormModel.DisplayName" />
                    <ValidationMessage For="@(() => CreateFormModel.DisplayName)" />
                </label>

                <label class="field">
                    <span>Club</span>
                    <InputText @bind-Value="CreateFormModel.Club" />
                    <ValidationMessage For="@(() => CreateFormModel.Club)" />
                </label>

                <label class="field">
                    <span>Ville</span>
                    <InputText @bind-Value="CreateFormModel.City" />
                    <ValidationMessage For="@(() => CreateFormModel.City)" />
                </label>

                <label class="field">
                    <span>Format prefere</span>
                    <InputSelect @bind-Value="CreateFormModel.PreferredFormat">
                        <option value="">Aucune preference</option>
                        <option value="Twice">Twice</option>
                        <option value="Time">Time</option>
                        <option value="Les deux">Les deux</option>
                    </InputSelect>
                    <ValidationMessage For="@(() => CreateFormModel.PreferredFormat)" />
                </label>

                <label class="field span-2">
                    <span>Cube favori</span>
                    <InputText @bind-Value="CreateFormModel.FavoriteCube" />
                    <ValidationMessage For="@(() => CreateFormModel.FavoriteCube)" />
                </label>

                <label class="field span-2">
                    <span>Bio</span>
                    <InputTextArea @bind-Value="CreateFormModel.Bio" />
                    <ValidationMessage For="@(() => CreateFormModel.Bio)" />
                </label>
            </div>

            <div class="admin-toggle-grid">
                <label class="admin-toggle-card">
                    <InputCheckbox @bind-Value="CreateFormModel.IsEnabled" />
                    <div>
                        <strong>Compte actif</strong>
                        <span>Permettre au nouvel utilisateur de se connecter immediatement.</span>
                    </div>
                </label>

                <label class="admin-toggle-card">
                    <InputCheckbox @bind-Value="CreateFormModel.IsEmailVerified" />
                    <div>
                        <strong>Email verifie</strong>
                        <span>Marquer l'adresse comme deja verifiee dans Keycloak.</span>
                    </div>
                </label>
            </div>

            <div class="modal-actions">
                <button class="button secondary" type="submit" disabled="@IsCreating">
                    @(IsCreating ? "Creation..." : "Creer l'utilisateur")
                </button>
            </div>
        </EditForm>
    </div>
</section>

<section class="modal @(ShowDeleteModal ? string.Empty : "hidden")" aria-hidden="@BoolString(!ShowDeleteModal)">
    <div class="modal-backdrop" @onclick="CloseDeleteModal"></div>
    <div class="modal-card admin-confirm-card">
        <div class="modal-head">
            <div>
                <p class="eyebrow">Suppression</p>
                <h2>Supprimer cet utilisateur</h2>
            </div>
            <button class="button ghost small" type="button" @onclick="CloseDeleteModal" disabled="@IsDeleting">Fermer</button>
        </div>

        @if (PendingDeleteUser is not null)
        {
            <p>
                Le compte <strong>@PendingDeleteUser.Username</strong> sera supprime de Keycloak
                ainsi que son profil du site. Cette action est irreversible.
            </p>
        }

        @if (!string.IsNullOrWhiteSpace(DeleteError))
        {
            <p class="profile-feedback error">@DeleteError</p>
        }

        <div class="modal-actions">
            <button class="button danger" type="button" @onclick="DeleteUserAsync" disabled="@IsDeleting">
                @(IsDeleting ? "Suppression..." : "Supprimer definitivement")
            </button>
            <button class="button ghost" type="button" @onclick="CloseDeleteModal" disabled="@IsDeleting">Annuler</button>
        </div>
    </div>
</section>

@code {
    private readonly AdminUserFormModel EditFormModel = new();
    private readonly AdminCreateUserFormModel CreateFormModel = new();
    private readonly List<AdminUserSummaryResponse> Users = [];

    private AdminUserDetailResponse? SelectedUser;
    private AdminUserSummaryResponse? PendingDeleteUser;
    private string? SelectedSubject;
    private string SearchTerm = string.Empty;
    private bool IsAuthenticated;
    private bool IsAdmin;
    private bool IsLoadingUsers = true;
    private bool IsLoadingDetail;
    private bool IsSaving;
    private bool IsCreating;
    private bool IsDeleting;
    private bool ShowEditModal;
    private bool ShowCreateModal;
    private bool ShowDeleteModal;
    private string? LoadError;
    private string? DetailError;
    private string? SaveError;
    private string? SaveMessage;
    private string? CreateError;
    private string? DeleteError;

    private List<AdminUserSummaryResponse> FilteredUsers
        => Users
            .Where(MatchesSearch)
            .ToList();

    private string HeroStatusTitle
        => !IsAuthenticated
            ? "Connexion requise"
            : !IsAdmin
                ? "Compte non admin"
                : IsLoadingUsers
                    ? "Chargement des utilisateurs"
                    : $"{Users.Count} comptes disponibles";

    private string HeroStatusDescription
        => !IsAuthenticated
            ? "Connecte-toi avec un compte admin pour ouvrir la zone d'administration."
            : !IsAdmin
                ? "Le compte actuel est authentifie mais ne dispose pas du role admin."
                : IsLoadingUsers
                    ? "Le site recupere les comptes et les profils deja relies a MySQL."
                    : "Le tableau permet maintenant les operations classiques d'ajout, modification et suppression.";

    protected override async Task OnInitializedAsync()
    {
        AuthenticationStateProvider.AuthenticationStateChanged += HandleAuthenticationStateChanged;
        await LoadUsersAsync();
    }

    private void HandleAuthenticationStateChanged(Task<AuthenticationState> authenticationStateTask)
        => _ = InvokeAsync(() => LoadUsersAsync(SelectedSubject));

    private async Task ReloadUsersAsync()
        => await LoadUsersAsync(SelectedSubject);

    private async Task LoadUsersAsync(string? preferredSubject = null, bool preserveFeedback = false)
    {
        LoadError = null;
        DetailError = null;

        if (!preserveFeedback)
        {
            SaveError = null;
            SaveMessage = null;
        }

        IsLoadingUsers = true;

        try
        {
            var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
            if (authState.User.Identity?.IsAuthenticated != true)
            {
                ResetAdminState();
                return;
            }

            IsAuthenticated = true;
            IsAdmin = authState.User.IsInRole("admin");

            if (!IsAdmin)
            {
                Users.Clear();
                SelectedSubject = null;
                SelectedUser = null;
                ShowEditModal = false;
                EditFormModel.Reset();
                return;
            }

            var response = await Http.GetAsync("api/admin/users");
            if (!response.IsSuccessStatusCode)
            {
                LoadError = await ReadErrorAsync(response, "La liste des utilisateurs n'a pas pu etre chargee.");
                Users.Clear();
                SelectedSubject = null;
                SelectedUser = null;
                ShowEditModal = false;
                EditFormModel.Reset();
                return;
            }

            var users = await response.Content.ReadFromJsonAsync<List<AdminUserSummaryResponse>>();
            Users.Clear();
            Users.AddRange(users ?? []);

            if (Users.Count == 0)
            {
                SelectedSubject = null;
                SelectedUser = null;
                ShowEditModal = false;
                EditFormModel.Reset();
                return;
            }

            var nextSubject = Users.Any(user => user.Subject == preferredSubject)
                ? preferredSubject
                : Users.Any(user => user.Subject == SelectedSubject)
                    ? SelectedSubject
                    : null;

            if (!string.IsNullOrWhiteSpace(nextSubject))
            {
                SelectedSubject = nextSubject;

                if (ShowEditModal)
                {
                    await LoadUserDetailAsync(nextSubject, keepFeedback: true);
                }
                else
                {
                    SelectedUser = null;
                    EditFormModel.Reset();
                }
            }
            else
            {
                SelectedSubject = null;
                SelectedUser = null;
                EditFormModel.Reset();
            }
        }
        catch (HttpRequestException)
        {
            LoadError = "Le service d'administration est temporairement indisponible.";
            Users.Clear();
            SelectedSubject = null;
            SelectedUser = null;
            ShowEditModal = false;
            EditFormModel.Reset();
        }
        catch (TaskCanceledException)
        {
            LoadError = "Le chargement de l'administration a pris trop de temps.";
            Users.Clear();
            SelectedSubject = null;
            SelectedUser = null;
            ShowEditModal = false;
            EditFormModel.Reset();
        }
        finally
        {
            IsLoadingUsers = false;
            StateHasChanged();
        }
    }

    private async Task SelectUserAsync(string subject)
    {
        SaveError = null;
        SaveMessage = null;
        ShowEditModal = true;
        await LoadUserDetailAsync(subject, keepFeedback: false);
    }

    private async Task LoadUserDetailAsync(string subject, bool keepFeedback)
    {
        if (!keepFeedback)
        {
            SaveError = null;
            SaveMessage = null;
        }

        IsLoadingDetail = true;
        DetailError = null;
        SelectedSubject = subject;

        try
        {
            var response = await Http.GetAsync($"api/admin/users/{Uri.EscapeDataString(subject)}");
            if (!response.IsSuccessStatusCode)
            {
                DetailError = await ReadErrorAsync(response, "La fiche utilisateur n'a pas pu etre chargee.");
                SelectedUser = null;
                return;
            }

            SelectedUser = await response.Content.ReadFromJsonAsync<AdminUserDetailResponse>();
            if (SelectedUser is null)
            {
                DetailError = "Le serveur a retourne une fiche vide.";
                return;
            }

            FillEditForm(SelectedUser);
        }
        catch (HttpRequestException)
        {
            DetailError = "Le detail utilisateur est temporairement indisponible.";
            SelectedUser = null;
        }
        catch (TaskCanceledException)
        {
            DetailError = "Le detail utilisateur a pris trop de temps a se charger.";
            SelectedUser = null;
        }
        finally
        {
            IsLoadingDetail = false;
            StateHasChanged();
        }
    }

    private async Task SaveUserAsync()
    {
        if (IsSaving || SelectedSubject is null)
        {
            return;
        }

        IsSaving = true;
        SaveError = null;
        SaveMessage = null;

        try
        {
            var payload = new AdminUpdateUserRequest
            {
                Username = EditFormModel.Username ?? string.Empty,
                Email = EditFormModel.Email,
                FirstName = EditFormModel.FirstName,
                LastName = EditFormModel.LastName,
                IsEnabled = EditFormModel.IsEnabled,
                IsEmailVerified = EditFormModel.IsEmailVerified,
                DisplayName = EditFormModel.DisplayName,
                Club = EditFormModel.Club,
                City = EditFormModel.City,
                PreferredFormat = EditFormModel.PreferredFormat,
                FavoriteCube = EditFormModel.FavoriteCube,
                Bio = EditFormModel.Bio,
            };

            var response = await Http.PutAsJsonAsync($"api/admin/users/{Uri.EscapeDataString(SelectedSubject)}", payload);
            if (!response.IsSuccessStatusCode)
            {
                SaveError = await ReadErrorAsync(response, "La mise a jour de l'utilisateur a echoue.");
                return;
            }

            SelectedUser = await response.Content.ReadFromJsonAsync<AdminUserDetailResponse>();
            if (SelectedUser is null)
            {
                SaveError = "Le serveur a retourne une fiche vide apres la sauvegarde.";
                return;
            }

            FillEditForm(SelectedUser);
            UpdateSummary(SelectedUser);
            SaveMessage = "La fiche utilisateur a bien ete mise a jour.";
        }
        catch (HttpRequestException)
        {
            SaveError = "Le service d'administration est temporairement indisponible.";
        }
        catch (TaskCanceledException)
        {
            SaveError = "La sauvegarde a pris trop de temps.";
        }
        finally
        {
            IsSaving = false;
        }
    }

    private void CloseEditModal()
    {
        if (IsSaving)
        {
            return;
        }

        ShowEditModal = false;
        DetailError = null;
    }

    private async Task ReloadSelectedUserAsync()
    {
        if (SelectedSubject is null)
        {
            return;
        }

        await LoadUserDetailAsync(SelectedSubject, keepFeedback: true);
    }

    private void OpenCreateModal()
    {
        CreateFormModel.Reset();
        CreateError = null;
        ShowCreateModal = true;
    }

    private void CloseCreateModal()
    {
        if (IsCreating)
        {
            return;
        }

        ShowCreateModal = false;
        CreateError = null;
    }

    private async Task CreateUserAsync()
    {
        if (IsCreating)
        {
            return;
        }

        IsCreating = true;
        CreateError = null;

        try
        {
            var payload = new AdminCreateUserRequest
            {
                Username = CreateFormModel.Username ?? string.Empty,
                Email = CreateFormModel.Email,
                Password = CreateFormModel.Password ?? string.Empty,
                ConfirmPassword = CreateFormModel.ConfirmPassword ?? string.Empty,
                FirstName = CreateFormModel.FirstName,
                LastName = CreateFormModel.LastName,
                IsEnabled = CreateFormModel.IsEnabled,
                IsEmailVerified = CreateFormModel.IsEmailVerified,
                DisplayName = CreateFormModel.DisplayName,
                Club = CreateFormModel.Club,
                City = CreateFormModel.City,
                PreferredFormat = CreateFormModel.PreferredFormat,
                FavoriteCube = CreateFormModel.FavoriteCube,
                Bio = CreateFormModel.Bio,
            };

            var response = await Http.PostAsJsonAsync("api/admin/users", payload);
            if (!response.IsSuccessStatusCode)
            {
                CreateError = await ReadErrorAsync(response, "La creation de l'utilisateur a echoue.");
                return;
            }

            var createdUser = await response.Content.ReadFromJsonAsync<AdminUserDetailResponse>();
            if (createdUser is null)
            {
                CreateError = "Le serveur a retourne une fiche vide apres la creation.";
                return;
            }

            ShowCreateModal = false;
            SaveMessage = $"L'utilisateur {createdUser.Username} a bien ete cree.";
            SaveError = null;
            await LoadUsersAsync(createdUser.Subject, preserveFeedback: true);
        }
        catch (HttpRequestException)
        {
            CreateError = "Le service d'administration est temporairement indisponible.";
        }
        catch (TaskCanceledException)
        {
            CreateError = "La creation a pris trop de temps.";
        }
        finally
        {
            IsCreating = false;
        }
    }

    private void PromptDeleteUser(AdminUserSummaryResponse user)
    {
        PendingDeleteUser = user;
        DeleteError = null;
        ShowDeleteModal = true;
    }

    private void CloseDeleteModal()
    {
        if (IsDeleting)
        {
            return;
        }

        ShowDeleteModal = false;
        DeleteError = null;
        PendingDeleteUser = null;
    }

    private async Task DeleteUserAsync()
    {
        if (IsDeleting || PendingDeleteUser is null)
        {
            return;
        }

        IsDeleting = true;
        DeleteError = null;

        try
        {
            var deletedUsername = PendingDeleteUser.Username;
            var deletedSubject = PendingDeleteUser.Subject;

            var response = await Http.DeleteAsync($"api/admin/users/{Uri.EscapeDataString(deletedSubject)}");
            if (!response.IsSuccessStatusCode)
            {
                DeleteError = await ReadErrorAsync(response, "La suppression de l'utilisateur a echoue.");
                return;
            }

            ShowDeleteModal = false;
            PendingDeleteUser = null;
            SaveError = null;
            SaveMessage = $"L'utilisateur {deletedUsername} a bien ete supprime.";

            var nextSubject = SelectedSubject == deletedSubject ? null : SelectedSubject;
            await LoadUsersAsync(nextSubject, preserveFeedback: true);
        }
        catch (HttpRequestException)
        {
            DeleteError = "Le service d'administration est temporairement indisponible.";
        }
        catch (TaskCanceledException)
        {
            DeleteError = "La suppression a pris trop de temps.";
        }
        finally
        {
            IsDeleting = false;
        }
    }

    private void UpdateSummary(AdminUserDetailResponse detail)
    {
        var summary = Users.FirstOrDefault(user => user.Subject == detail.Subject);
        if (summary is null)
        {
            return;
        }

        summary.Username = detail.Username;
        summary.Email = detail.Email;
        summary.IdentityDisplayName = detail.IdentityDisplayName;
        summary.SiteDisplayName = detail.DisplayName;
        summary.IsEnabled = detail.IsEnabled;
        summary.IsEmailVerified = detail.IsEmailVerified;
        summary.HasSiteProfile = detail.HasSiteProfile;
        summary.Club = detail.Club;
        summary.City = detail.City;
        summary.PreferredFormat = detail.PreferredFormat;
        summary.AccountCreatedUtc = detail.AccountCreatedUtc;
        summary.SiteProfileUpdatedUtc = detail.SiteProfileUpdatedUtc;
    }

    private void FillEditForm(AdminUserDetailResponse user)
    {
        EditFormModel.Username = user.Username;
        EditFormModel.Email = user.Email;
        EditFormModel.FirstName = user.FirstName;
        EditFormModel.LastName = user.LastName;
        EditFormModel.IsEnabled = user.IsEnabled;
        EditFormModel.IsEmailVerified = user.IsEmailVerified;
        EditFormModel.DisplayName = user.DisplayName;
        EditFormModel.Club = user.Club;
        EditFormModel.City = user.City;
        EditFormModel.PreferredFormat = user.PreferredFormat;
        EditFormModel.FavoriteCube = user.FavoriteCube;
        EditFormModel.Bio = user.Bio;
    }

    private void ResetAdminState()
    {
        IsAuthenticated = false;
        IsAdmin = false;
        Users.Clear();
        SelectedSubject = null;
        SelectedUser = null;
        PendingDeleteUser = null;
        ShowEditModal = false;
        ShowCreateModal = false;
        ShowDeleteModal = false;
        EditFormModel.Reset();
        CreateFormModel.Reset();
    }

    private bool MatchesSearch(AdminUserSummaryResponse user)
    {
        var search = SearchTerm.Trim();
        if (string.IsNullOrWhiteSpace(search))
        {
            return true;
        }

        return Contains(user.Username, search)
            || Contains(user.Email, search)
            || Contains(user.IdentityDisplayName, search)
            || Contains(user.SiteDisplayName, search)
            || Contains(user.Club, search)
            || Contains(user.City, search);
    }

    private static bool Contains(string? value, string search)
        => value?.Contains(search, StringComparison.OrdinalIgnoreCase) == true;

    private string BuildTableRowClass(AdminUserSummaryResponse user)
        => string.Equals(SelectedSubject, user.Subject, StringComparison.Ordinal)
            ? "is-selected"
            : string.Empty;

    private string BuildEditModalTitle()
    {
        if (SelectedUser is not null)
        {
            return !string.IsNullOrWhiteSpace(SelectedUser.DisplayName)
                ? SelectedUser.DisplayName
                : SelectedUser.Username;
        }

        var summary = Users.FirstOrDefault(user => user.Subject == SelectedSubject);
        return summary?.IdentityDisplayName
            ?? summary?.Username
            ?? "Modifier un utilisateur";
    }

    private static string BuildUserCardFootnote(AdminUserSummaryResponse user)
        => user.SiteProfileUpdatedUtc is not null
            ? FormatDate(user.SiteProfileUpdatedUtc)
            : user.AccountCreatedUtc is not null
                ? FormatDate(user.AccountCreatedUtc)
                : "Non disponible";

    private static async Task<string> ReadErrorAsync(HttpResponseMessage response, string fallbackMessage)
    {
        try
        {
            var error = await response.Content.ReadFromJsonAsync<ApiErrorMessage>();
            if (!string.IsNullOrWhiteSpace(error?.Message))
            {
                return error.Message;
            }
        }
        catch
        {
        }

        return response.StatusCode switch
        {
            HttpStatusCode.Unauthorized => "La session a expire. Reconnecte-toi puis recharge la page.",
            HttpStatusCode.Forbidden => "Ce compte n'a pas le role admin requis pour cette action.",
            HttpStatusCode.NotFound => "Cet utilisateur n'existe plus ou n'est plus disponible.",
            _ => fallbackMessage,
        };
    }

    private static string FormatDate(DateTime? value)
        => value is null
            ? "Non disponible"
            : value.Value.ToLocalTime().ToString("dd MMM yyyy 'a' HH:mm", CultureInfo.GetCultureInfo("fr-FR"));

    private static string BoolString(bool value)
        => value ? "true" : "false";

    public void Dispose()
        => AuthenticationStateProvider.AuthenticationStateChanged -= HandleAuthenticationStateChanged;

    private sealed class ApiErrorMessage
    {
        public string? Message { get; set; }
    }

    private class AdminUserFormModel
    {
        [Required(ErrorMessage = "Le nom d'utilisateur est obligatoire.")]
        [MaxLength(120, ErrorMessage = "Le nom d'utilisateur doit rester sous 120 caracteres.")]
        public string? Username { get; set; }

        [MaxLength(255, ErrorMessage = "L'email doit rester sous 255 caracteres.")]
        [EmailAddress(ErrorMessage = "L'email n'est pas valide.")]
        public string? Email { get; set; }

        [MaxLength(120, ErrorMessage = "Le prenom doit rester sous 120 caracteres.")]
        public string? FirstName { get; set; }

        [MaxLength(120, ErrorMessage = "Le nom doit rester sous 120 caracteres.")]
        public string? LastName { get; set; }

        public bool IsEnabled { get; set; } = true;

        public bool IsEmailVerified { get; set; }

        [MaxLength(120, ErrorMessage = "Le nom affiche doit rester sous 120 caracteres.")]
        public string? DisplayName { get; set; }

        [MaxLength(120, ErrorMessage = "Le club doit rester sous 120 caracteres.")]
        public string? Club { get; set; }

        [MaxLength(120, ErrorMessage = "La ville doit rester sous 120 caracteres.")]
        public string? City { get; set; }

        [MaxLength(40, ErrorMessage = "Le format prefere doit rester sous 40 caracteres.")]
        public string? PreferredFormat { get; set; }

        [MaxLength(120, ErrorMessage = "Le cube favori doit rester sous 120 caracteres.")]
        public string? FavoriteCube { get; set; }

        [MaxLength(1200, ErrorMessage = "La bio doit rester sous 1200 caracteres.")]
        public string? Bio { get; set; }

        public virtual void Reset()
        {
            Username = string.Empty;
            Email = string.Empty;
            FirstName = string.Empty;
            LastName = string.Empty;
            IsEnabled = true;
            IsEmailVerified = false;
            DisplayName = string.Empty;
            Club = string.Empty;
            City = string.Empty;
            PreferredFormat = string.Empty;
            FavoriteCube = string.Empty;
            Bio = string.Empty;
        }
    }

    private sealed class AdminCreateUserFormModel : AdminUserFormModel
    {
        [Required(ErrorMessage = "Le mot de passe est obligatoire.")]
        [MinLength(8, ErrorMessage = "Le mot de passe doit contenir au moins 8 caracteres.")]
        public string? Password { get; set; }

        [Required(ErrorMessage = "La confirmation est obligatoire.")]
        [Compare(nameof(Password), ErrorMessage = "Les mots de passe ne correspondent pas.")]
        public string? ConfirmPassword { get; set; }

        public override void Reset()
        {
            base.Reset();
            Password = string.Empty;
            ConfirmPassword = string.Empty;
        }
    }
}
