using Microsoft.EntityFrameworkCore; using PnvPanel.Application.Auth; using PnvPanel.Application.Common.Interfaces; using PnvPanel.Application.Common.Messaging; using PnvPanel.Application.Common.Models; using PnvPanel.Application.Support; using PnvPanel.Domain.Audit; using PnvPanel.Domain.Support; namespace PnvPanel.Application.Admin.Support; public sealed class ApproveRoleRequestCommandHandler( IAppDbContext dbContext, IRoleService roleService, IRealtimeNotifier notifier, ITelegramNotifier telegramNotifier, ICurrentUser currentUser ) : ICommandHandler { public async Task Handle( ApproveRoleRequestCommand command, CancellationToken cancellationToken ) { if (currentUser.UserId is not { } adminId) return Result.Failure(AuthErrors.Unauthorized); var ticket = await dbContext.SupportTickets.FirstOrDefaultAsync( t => t.Id == command.TicketId, cancellationToken ); if (ticket is null) return Result.Failure(SupportErrors.NotFound); if (ticket.Type != TicketType.RoleRequest) return Result.Failure(SupportErrors.NotRoleRequest); if (ticket.Status != TicketStatus.Open) return Result.Failure(SupportErrors.NotOpen); Guid roleId; if (ticket.RequestedRoleId is { } existingRoleId) { roleId = existingRoleId; } else { var createResult = await roleService.CreateRoleAsync( ticket.ProposedRoleName!, ticket.ProposedMaxConfigs!.Value, ticket.ProposedMaxIpLimit!.Value, billingEnabled: false, cancellationToken ); if (!createResult.IsSuccess) return Result.Failure(createResult.Error); roleId = createResult.Value.Id; } var assignResult = await roleService.ChangeUserRoleAsync( ticket.UserId, roleId, cancellationToken ); if (!assignResult.IsSuccess) return assignResult; ticket.Resolve(); dbContext.AuditLogs.Add( AuditLog.Create( adminId, "RoleRequestApproved", "SupportTicket", ticket.Id.ToString(), metadata: null, AuditSource.Web ) ); await notifier.NotifyTicketUpdatedAsync(ticket.Id, ticket.UserId, cancellationToken); await telegramNotifier.NotifyUserAsync( ticket.UserId, "✅ Ваша заявка на роль одобрена.", $"/support?ticket={ticket.Id}", cancellationToken ); return Result.Success(); } }