using Application.Abstractions.Data; using Application.Abstractions.Messaging; using Application.Abstractions.YouTube; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; namespace Application.Features.Api.Studio.DisconnectYouTube; internal sealed class Handler( IAppDbContext db, IYouTubeChannelCache channelCache, IGoogleOAuthService oauthService, ILogger logger ) : ICommandHandler { public async Task Handle(Command request, CancellationToken ct) { var channel = await db.Channel.FirstOrDefaultAsync(c => c.MemberID == request.MemberID && c.IsActive, ct); if (channel is null) { throw new InvalidOperationException("연동된 채널이 없습니다."); } // OAuth 토큰 조회 → revoke → 삭제 var oauthToken = await db.MemberOAuthToken.FirstOrDefaultAsync(t => t.MemberID == request.MemberID && t.Provider == "YouTube", ct); if (oauthToken is not null) { // Google OAuth revoke (실패해도 무시) await oauthService.RevokeTokenAsync(oauthToken.AccessTokenEnc, ct); db.MemberOAuthToken.Remove(oauthToken); } // 채널 비활성화 channel.Deactivate(); // Redis 캐시 삭제 var cacheKey = channel.YouTubeChannelID ?? channel.SID; await channelCache.RemoveAsync(cacheKey); await db.SaveChangesAsync(ct); logger.LogInformation("YouTube 연동 해지: MemberID={MemberID}, ChannelID={ChannelID}", request.MemberID, channel.ID); } }