@page "/admin/users"
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Identity
@attribute [Authorize(Roles = "Admin")]
@rendermode InteractiveServer
@inject UserManager<ApplicationUser> UserManager
@inject IDbContextFactory<ApplicationDbContext> DbFactory
@inject AuthenticationStateProvider AuthState

<PageTitle>Admin · Users</PageTitle>

<div class="d-flex justify-content-between align-items-center mb-3">
    <h1>Users</h1>
    <a class="btn btn-primary" href="admin/invites">Manage invitations</a>
</div>

@if (users is null)
{
    <p>Loading…</p>
}
else
{
    <table class="table align-middle">
        <thead>
            <tr><th>Name</th><th>Email</th><th>Joined</th><th>Roles</th><th>Status</th><th></th></tr>
        </thead>
        <tbody>
            @foreach (var u in users)
            {
                <tr>
                    <td>@u.DisplayName</td>
                    <td>@u.Email</td>
                    <td class="small text-secondary">@u.CreatedAt.ToString("yyyy-MM-dd")</td>
                    <td>
                        @if (adminIds.Contains(u.Id))
                        {
                            <span class="badge bg-primary">Admin</span>
                        }
                        else
                        {
                            <span class="badge bg-secondary">User</span>
                        }
                    </td>
                    <td>
                        @if (u.IsDisabled)
                        {
                            <span class="badge bg-danger">Disabled</span>
                        }
                        else
                        {
                            <span class="badge bg-success">Active</span>
                        }
                    </td>
                    <td class="text-end">
                        @if (u.Id != currentUserId)
                        {
                            <button class="btn btn-outline-secondary btn-sm" @onclick="() => ToggleAdmin(u)">
                                @(adminIds.Contains(u.Id) ? "Revoke admin" : "Make admin")
                            </button>
                            <button class="btn btn-sm @(u.IsDisabled ? "btn-outline-success" : "btn-outline-danger")"
                                    @onclick="() => ToggleDisabled(u)">
                                @(u.IsDisabled ? "Enable" : "Disable")
                            </button>
                        }
                        else
                        {
                            <span class="text-secondary small">(you)</span>
                        }
                    </td>
                </tr>
            }
        </tbody>
    </table>
}

@code {
    private List<ApplicationUser>? users;
    private HashSet<string> adminIds = new();
    private string? currentUserId;

    protected override async Task OnInitializedAsync()
    {
        currentUserId = await AuthState.GetUserIdAsync();
        await LoadAsync();
    }

    private async Task LoadAsync()
    {
        await using var db = await DbFactory.CreateDbContextAsync();
        users = await db.Users.OrderBy(u => u.DisplayName).ToListAsync();
        var admins = await UserManager.GetUsersInRoleAsync("Admin");
        adminIds = admins.Select(a => a.Id).ToHashSet();
    }

    private async Task ToggleAdmin(ApplicationUser u)
    {
        var user = await UserManager.FindByIdAsync(u.Id);
        if (user is null) return;
        if (adminIds.Contains(u.Id))
            await UserManager.RemoveFromRoleAsync(user, "Admin");
        else
            await UserManager.AddToRoleAsync(user, "Admin");
        await LoadAsync();
    }

    private async Task ToggleDisabled(ApplicationUser u)
    {
        var user = await UserManager.FindByIdAsync(u.Id);
        if (user is null) return;
        var disable = !user.IsDisabled;
        user.IsDisabled = disable;
        await UserManager.SetLockoutEnabledAsync(user, true);
        await UserManager.SetLockoutEndDateAsync(user, disable ? DateTimeOffset.MaxValue : null);
        await UserManager.UpdateAsync(user);
        // Invalidate any active session by rotating the security stamp.
        await UserManager.UpdateSecurityStampAsync(user);
        await LoadAsync();
    }
}
