using System.Diagnostics.CodeAnalysis;
using Microsoft.JSInterop;
using RpgRoller.Contracts;
using RpgRoller.Domain;

namespace RpgRoller.Components.Pages;

[ExcludeFromCodeCoverage]
public sealed class WorkspaceAdminCoordinator(WorkspaceState state, WorkspaceFeedbackService feedback, IJSRuntime js, RpgRollerApiClient apiClient, WorkspaceQueryService workspaceQuery, Action clearAuthenticatedState, Func<Task> stopStateEventsAsync, Func<string?, Task> onLoggedOutAsync)
{
    public async Task EnsureAdminUsersLoadedAsync()
    {
        if (!state.IsCurrentUserAdmin || state.HasLoadedAdminUsers || state.IsAdminDataLoading)
            return;

        state.IsAdminDataLoading = true;
        try
        {
            await ReloadAdminUsersAsync();
        }
        catch (ApiRequestException ex) when (ex.StatusCode == 401)
        {
            clearAuthenticatedState();
            await stopStateEventsAsync();
            await onLoggedOutAsync("Session expired. Please log in again.");
        }
        catch (ApiRequestException ex)
        {
            feedback.SetStatus(ex.Message, true);
        }
        finally
        {
            state.IsAdminDataLoading = false;
        }
    }

    public async Task ToggleAdminRoleAsync(AdminUserSummary user)
    {
        if (state.IsMutating || state.User is null || !state.IsCurrentUserAdmin || user.Id == state.User.Id)
            return;

        state.IsMutating = true;
        try
        {
            IReadOnlyList<string> roles = HasAdminRole(user) ? Array.Empty<string>() : [UserRoles.Admin];
            _ = await apiClient.RequestAsync<AdminUserSummary>("PUT", $"/api/admin/users/{user.Id}/roles", new UpdateUserRolesRequest(roles));

            await ReloadAdminUsersAsync();
            feedback.SetStatus("User roles updated.", false);
        }
        catch (ApiRequestException ex)
        {
            feedback.SetStatus(ex.Message, true);
        }
        finally
        {
            state.IsMutating = false;
        }
    }

    public async Task DeleteUserAsync(AdminUserSummary user)
    {
        if (state.IsMutating || state.User is null || !state.IsCurrentUserAdmin || user.Id == state.User.Id)
            return;

        var confirmed = await js.InvokeAsync<bool>("confirm", $"Delete user '{user.Username}'?");
        if (!confirmed)
            return;

        state.IsMutating = true;
        try
        {
            _ = await apiClient.RequestAsync<bool>("DELETE", $"/api/admin/users/{user.Id}");
            await ReloadAdminUsersAsync();
            feedback.SetStatus("User deleted.", false);
        }
        catch (ApiRequestException ex)
        {
            feedback.SetStatus(ex.Message, true);
        }
        finally
        {
            state.IsMutating = false;
        }
    }

    private async Task ReloadAdminUsersAsync()
    {
        state.AdminUsers = (await workspaceQuery.GetAdminUsersAsync()).OrderBy(user => user.Username, StringComparer.OrdinalIgnoreCase).ToList();

        state.HasLoadedAdminUsers = true;
    }

    private static bool HasAdminRole(AdminUserSummary user)
    {
        return user.Roles.Contains(UserRoles.Admin, StringComparer.OrdinalIgnoreCase);
    }
}