using Application.Abstractions.Data; using Application.Abstractions.Messaging; using Domain.Entities.Donations; using Microsoft.EntityFrameworkCore; using SharedKernel.Results; namespace Application.Features.Api.ChannelTitle.SelectMyTitle; internal sealed class Handler(IAppDbContext db) : ICommandHandler { public async Task Handle(Command request, CancellationToken ct) { if (request.TitleID.HasValue) { var title = await db.ChannelTitle.FirstOrDefaultAsync(t => t.ID == request.TitleID.Value, ct); if (title is null || title.ChannelID != request.ChannelID) { return Result.Failure(Error.NotFound("ChannelTitle.NotFound", "칭호를 찾을 수 없습니다.")); } if (!title.IsActive) { return Result.Failure(Error.Problem("ChannelTitle.Inactive", "비활성화된 칭호는 선택할 수 없습니다.")); } var stats = await db.DonorChannelStats.AsNoTracking() .FirstOrDefaultAsync(s => s.DonorMemberID == request.MemberID && s.ChannelID == request.ChannelID, ct); if (stats is null || stats.CumulativeAmount < title.MinAmount) { return Result.Failure(Error.Forbidden("ChannelTitle.NotAcquired", "아직 획득하지 못한 칭호입니다.")); } } var selection = await db.DonorTitleSelection .FirstOrDefaultAsync(s => s.DonorMemberID == request.MemberID && s.ChannelID == request.ChannelID, ct); if (selection is null) { selection = DonorTitleSelection.Create(request.MemberID, request.ChannelID, request.TitleID); await db.DonorTitleSelection.AddAsync(selection, ct); } else { selection.Update(request.TitleID); } await db.SaveChangesAsync(ct); return Result.Success(); } }