using Microsoft.AspNetCore.Http.HttpResults;
using RpgRoller.Contracts;
using RpgRoller.Domain;
using RpgRoller.Hosting;
using RpgRoller.Services;

namespace RpgRoller.Api;

internal static class AdminEndpoints
{
    public static RouteGroupBuilder MapAdminEndpoints(this RouteGroupBuilder group)
    {
        group.MapGet("/admin/users", (HttpContext context, IGameService game) =>
        {
            var result = game.GetUsers(context.GetRequiredSessionToken());
            return ApiResultMapper.ToApiResult(result);
        });

        group.MapPut("/admin/users/{userId:guid}/roles", (Guid userId, UpdateUserRolesRequest request, HttpContext context, IGameService game) =>
        {
            var result = game.UpdateUserRoles(context.GetRequiredSessionToken(), userId, request.Roles);
            return ApiResultMapper.ToApiResult(result);
        });

        group.MapDelete("/admin/users/{userId:guid}", (Guid userId, HttpContext context, IGameService game) =>
        {
            var result = game.DeleteUser(context.GetRequiredSessionToken(), userId);
            return ApiResultMapper.ToApiResult(result);
        });

        group.MapGet("/admin/database", Results<FileStreamHttpResult, BadRequest<ApiError>, UnauthorizedHttpResult> (HttpContext context, IGameService game, SqliteDatabaseFile databaseFile) =>
        {
            var sessionToken = context.GetRequiredSessionToken();
            var user = game.GetUserBySession(sessionToken);
            if (user is null)
                return TypedResults.Unauthorized();

            if (!user.Roles.Contains(UserRoles.Admin, StringComparer.OrdinalIgnoreCase))
                return ApiResultMapper.ToBadRequest(new("forbidden", "Admin role is required."));

            if (string.IsNullOrWhiteSpace(databaseFile.Path) || !File.Exists(databaseFile.Path))
                return ApiResultMapper.ToBadRequest(new("database_unavailable", "SQLite database file is not available."));

            var stream = new FileStream(databaseFile.Path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
            return TypedResults.File(stream, "application/octet-stream", Path.GetFileName(databaseFile.Path));
        });

        return group;
    }
}