using Application.Abstractions.Data; using Application.Abstractions.Messaging; using Domain.Entities.Donations; using Microsoft.EntityFrameworkCore; namespace Application.Features.Api.DonationRank.SaveConfig; internal sealed class Handler(IAppDbContext db) : ICommandHandler { public async Task Handle(Command r, CancellationToken ct) { // 같은 기간 타입 동시 활성 검증 if (r.IsActive) { if (r.Period == Domain.Entities.Donations.ValueObject.RankPeriodType.Custom && r.StartAt.HasValue && r.EndAt.HasValue) { // 사용자 지정: 기간 겹침 검증 var overlap = await db.DonationRankConfig .AnyAsync(c => c.ChannelID == r.ChannelID && c.IsActive && c.ID != (r.ID ?? 0) && c.Period == Domain.Entities.Donations.ValueObject.RankPeriodType.Custom && c.StartAt != null && c.EndAt != null && c.StartAt < r.EndAt && c.EndAt > r.StartAt, ct); if (overlap) { throw new InvalidOperationException("해당 기간에 이미 활성화된 순위 설정이 존재합니다."); } } else { // 고정 기간(일간/주간/월간/연간/전체): 같은 타입 1개만 var duplicate = await db.DonationRankConfig .AnyAsync(c => c.ChannelID == r.ChannelID && c.IsActive && c.ID != (r.ID ?? 0) && c.Period == r.Period, ct); if (duplicate) { throw new InvalidOperationException("같은 기간 유형의 활성화된 순위 설정이 이미 존재합니다."); } } } if (r.ID.HasValue) { var config = await db.DonationRankConfig .FirstOrDefaultAsync(c => c.ID == r.ID.Value && c.ChannelID == r.ChannelID, ct); if (config is null) { throw new KeyNotFoundException("설정을 찾을 수 없습니다."); } config.Update( r.Title, r.Theme, r.Period, r.StartAt, r.EndAt, r.IsShowAmount, r.MaxRankCount, r.NameMode, r.IsActive, r.TitleFontFamily, r.TitleFontSizePx, r.TitleFontColor, r.NameDisplayType, r.IsShowDonationCount, r.IsShowGradeIcon, r.IsShowMemberIcon, r.Rank1FontFamily, r.Rank1FontSizePx, r.Rank1FontColor, r.Rank2FontFamily, r.Rank2FontSizePx, r.Rank2FontColor, r.Rank3FontFamily, r.Rank3FontSizePx, r.Rank3FontColor ); } else { var config = DonationRankConfig.Create( r.ChannelID, r.MemberID, r.Title, r.Theme, r.Period, r.StartAt, r.EndAt, r.IsShowAmount, r.MaxRankCount, r.NameMode, r.IsActive, r.TitleFontFamily, r.TitleFontSizePx, r.TitleFontColor, r.NameDisplayType, r.IsShowDonationCount, r.IsShowGradeIcon, r.IsShowMemberIcon, r.Rank1FontFamily, r.Rank1FontSizePx, r.Rank1FontColor, r.Rank2FontFamily, r.Rank2FontSizePx, r.Rank2FontColor, r.Rank3FontFamily, r.Rank3FontSizePx, r.Rank3FontColor ); db.DonationRankConfig.Add(config); } await db.SaveChangesAsync(ct); } }