using PostFundManagement.Domain; using PostFundManagement.Domain.Abstractions; using PostFundManagement.Domain.Errors; using PostFundManagement.Domain.Extensions; using PostFundManagement.Domain.Models; using PostFundManagement.Infrastructure.Database; namespace PostFundManagement.Application.Services.Communications; public sealed class CommunicationsService(IDbContextFactory contextFactory) : IService { public async ValueTask> SendInviteAsync(InviteRequest request, Guid userId, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); var invite = new Domain.Entities.Invite { OrganisationId = request.OrganisationId, InvitedOrganisationId = request.InvitedOrganisationId, AwardId = request.AwardId, ContractId = request.ContractId, Recipient = request.Recipient, CreatedBy = userId, CreatedAt = DateTime.UtcNow }; context.Invites.Add(invite); context.Notifications.Add(new Domain.Entities.Notification { OrganisationId = request.OrganisationId, Recipient = request.Recipient, Platform = request.Platform, Status = NotificationStatus.Pending, Subject = "Invitation to Onboard", Message = request.Message, CreatedAt = DateTime.UtcNow }); return await context.SaveChangesAsync(cancellationToken) > 0 ? Result.Ok(invite.Map()) : Result.Fail(CreateError.New); })); public async ValueTask> GetInvitesAsync(Pagination pagination, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); var invites = await context.Invites.AsNoTracking() .OrderByDescending(i => i.CreatedAt) .Skip((pagination.Page - 1) * pagination.PageSize) .Take(pagination.PageSize) .ToListAsync(cancellationToken); return Result.Ok(invites.Select(i => i.Map()).ToArray()); })); public async ValueTask> GetApplicantInviteAsync(Guid userId, CancellationToken cancellationToken) => await Result.Try((Func>>)(async () => { await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); var invite = await context.Invites.AsNoTracking().FirstOrDefaultAsync(i => i.Recipient == userId, cancellationToken); return invite is not null ? Result.Ok(invite.Map()) : Result.Fail(NotFoundError.New); })); }