@page "/manage/users"
@using Microsoft.AspNetCore.Identity
@using Wave.Data
@using Humanizer
@using Wave.Utilities

@rendermode InteractiveServer
@attribute [Authorize(Policy = "RoleAssignPermissions")]
@attribute [StreamRendering]

@inject RoleManager<IdentityRole> RoleManager
@inject UserManager<ApplicationUser> UserManager
@inject IStringLocalizer<ManageUsers> Localizer
@inject IMessageDisplay Toast

<PageTitle>@(Localizer["Title"] + TitlePostfix)</PageTitle>

<h1 class="text-3xl lg:text-5xl font-light mb-6 text-primary">@Localizer["Title"]</h1> 

<ModalComponent Id="@ModalId">
    <ChildContent>
        <InputLabelComponent LabelText="@Localizer["UserName_Label"]">
            <InputText class="input input-bordered w-full" type="email" autocomplete="off"
                       @bind-Value="@UserName" />
        </InputLabelComponent>
    </ChildContent>
    <Actions>
        <button class="btn btn-primary" @onclick="Add">@Localizer["UserName_Submit"]</button>
    </Actions>
</ModalComponent>

<section class="mb-3 overflow-x-auto">
    <h3 class="text-xl lg:text-3xl mb-2">
        @Localizer[CurrentRole.ToString().Pluralize()]
    </h3>
    <div class="flex gap-2">
        <InputSelect class="select select-bordered select-sm w-full max-w-xs" Value="CurrentRole"
                     ValueExpression="() => CurrentRole"
                     TValue="Role" ValueChanged="async c => await LoadAsync(c)">
            @foreach (var role in Enum.GetValues<Role>()) {
                <option value="@role">@Localizer[role.ToString()]</option>
            }
        </InputSelect>
        <button class="btn btn-sm btn-square btn-ghost text-success" onclick="@(ModalId).showModal()">
            <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
                <path stroke-linecap="round" stroke-linejoin="round" d="M12 9v6m3-3H9m12 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
            </svg>
        </button>
    </div>
    @if (Busy) {
        <div class="flex place-content-center">
            <span class="loading loading-spinner loading-lg"></span>
        </div>
    } else {
        <UserTable Users="Users" RemoveCallback="@(async u => await RemoveAsync(u, CurrentRole))"/>
    }
</section>

@code {
    [CascadingParameter(Name = "TitlePostfix")]
	private string TitlePostfix { get; set; } = default!;
    private string ModalId { get; } = "UserDialog";

	[CascadingParameter]
	private Task<AuthenticationState> AuthenticationState { get; set; } = default!;
	private ApplicationUser? User { get; set; }
    private Role CurrentRole { get; set; } = Role.Admin;
    private List<ApplicationUser> Users { get; } = [];
	private bool Busy { get; set; }

    private string UserName { get; set; }

	protected override async Task OnAfterRenderAsync(bool firstRender) {
		if (!firstRender) return;
		var state = await AuthenticationState;
		User = await UserManager.GetUserAsync(state.User);
        await LoadAsync(CurrentRole);
    }

    private async Task LoadAsync(Role role) {
        try {
            Busy = true;
            var users = await UserManager.GetUsersInRoleAsync(role.ToString());
            Users.Clear();
            CurrentRole = role;
            Users.AddRange(users);
        } finally {
            Busy = false;
        }
        await InvokeAsync(StateHasChanged);
    }

    private async Task Add() {
	    if (User is null) return;
        var user = await UserManager.FindByNameAsync(UserName);

        if (user is null) {
            Toast.ShowError(Localizer["Error_UserNotFound"]);
            return;
        }
        if (user.Id == User.Id) {
	        Toast.ShowError(Localizer["Error_EditSelf"]);
	        return;
        }

        if (!await RoleManager.RoleExistsAsync(CurrentRole.ToString())) {
            var result = await RoleManager.CreateAsync(new IdentityRole(CurrentRole.ToString()));

            if (result.Succeeded is not true) {
                Toast.ShowError(Localizer["Error_CreateRole"]);
                return;
            }
        }
        await UserManager.AddToRoleAsync(user, CurrentRole.ToString());
        await LoadAsync(CurrentRole);
        Toast.ShowSuccess(Localizer["Success_AddUser"]);
    }

	private async Task RemoveAsync(ApplicationUser user, Role role) {
		if (User is null) return;
		if (user.Id == User.Id) {
			Toast.ShowError(Localizer["Error_EditSelf"]);
			return;
		}
		await UserManager.RemoveFromRoleAsync(user, role.ToString());
        Toast.ShowSuccess(Localizer["Success_RemoveUser"]);
        await LoadAsync(CurrentRole);
    }

    private enum Role {
        Author, Reviewer, Moderator, Admin
    }
}
