using System.Text.RegularExpressions; using Application.Abstractions.Data; using Application.Abstractions.Messaging; using SharedKernel.Results; using Microsoft.EntityFrameworkCore; namespace Application.Features.Admin.Channel.List.Update; public sealed class Handler(IAppDbContext db) : ICommandHandler { public async Task Handle(Command request, CancellationToken ct) { var channel = await db.Channel.FirstOrDefaultAsync(c => c.ID == request.ID, ct); if (channel is null) { return Result.Failure(Error.NotFound("Channel.NotFound", "채널을 찾을 수 없습니다.")); } // 후원 코드 사전 검증 (자기 자신은 중복에서 제외) string? normalizedDonationCode = null; if (!string.IsNullOrWhiteSpace(request.DonationCode)) { var trimmed = request.DonationCode.Trim(); if (!Regex.IsMatch(trimmed, "^[A-Za-z0-9]{4,7}$")) { return Result.Failure(Error.Problem("DonationCode.InvalidFormat", "후원 코드는 4~7자 영문/숫자만 가능합니다.")); } normalizedDonationCode = trimmed.ToUpperInvariant(); var codeTaken = await db.Channel.AnyAsync(c => c.DonationCode == normalizedDonationCode && c.ID != request.ID, ct); if (codeTaken) { return Result.Failure(Error.Conflict("DonationCode.Duplicate", "이미 사용 중인 후원 코드입니다.")); } } channel.Update( request.Name, request.Handle, request.YouTubeUrl, request.PlatformFeeRate, request.StoreCommissionRate, request.IsVerified, request.IsActive ); channel.SetDonationCodeByAdmin(normalizedDonationCode); try { await db.SaveChangesAsync(ct); } catch (DbUpdateException) { return Result.Failure(Error.Conflict("DonationCode.Duplicate", "이미 사용 중인 후원 코드입니다.")); } return Result.Success(); } }