using Application.Abstractions.Messaging;
using Application.Abstractions.Data;
using Domain.Entities.Members;
using MemberEntity = Domain.Entities.Members.Member;
using ChannelEntity = Domain.Entities.Members.Channel;
using Microsoft.EntityFrameworkCore;

namespace Application.Features.Admin.Member.List.Create;

public sealed class Handler(IAppDbContext db) : ICommandHandler<Command>
{
    public async Task Handle(Command request, CancellationToken ct)
    {
        // 이메일 중복 체크
        if (await db.Member.AnyAsync(x => x.Email == request.Email, ct))
        {
            throw new InvalidOperationException("이미 등록된 이메일입니다.");
        }

        // 별명 중복 체크
        if (request.Name is not null && await db.Member.AnyAsync(x => x.Name == request.Name, ct))
        {
            throw new InvalidOperationException("이미 등록된 별명입니다.");
        }

        // 회원 생성
        var member = MemberEntity.Create(request.Email);

        await db.Member.AddAsync(member, ct);
        await db.SaveChangesAsync(ct);

        // 기본 정보 업데이트
        await db.Member.Where(x => x.ID == member.ID).ExecuteUpdateAsync(s => s
            .SetProperty(x => x.MemberGradeID, request.MemberGradeID)
            .SetProperty(x => x.Name, request.Name)
            .SetProperty(x => x.Password, request.Password)
            .SetProperty(x => x.FirstName, request.FirstName)
            .SetProperty(x => x.LastName, request.LastName)
            .SetProperty(x => x.Intro, request.Intro)
            .SetProperty(x => x.Summary, request.Summary)
            .SetProperty(x => x.Phone, request.Phone)
            .SetProperty(x => x.Birthday, request.Birthday)
            .SetProperty(x => x.Gender, request.Gender)
            .SetProperty(x => x.Thumb, request.ThumbUrl)
            .SetProperty(x => x.Icon, request.IconUrl)
            .SetProperty(x => x.IsEmailVerified, request.IsEmailVerified)
            .SetProperty(x => x.IsAuthCertified, request.IsAuthCertified)
            .SetProperty(x => x.IsDenied, request.IsDenied)
            .SetProperty(x => x.IsAdmin, request.IsAdmin)
            .SetProperty(x => x.IsWithdraw, request.IsWithdraw),
        ct);

        // MemberApprove 생성
        await db.MemberApprove.AddAsync(
            MemberApprove.Create(member.ID)
        , ct);

        // YouTube 채널 정보가 있는 경우
        if (!string.IsNullOrWhiteSpace(request.YouTubeSID) &&
            !string.IsNullOrWhiteSpace(request.YouTubeName) &&
            !string.IsNullOrWhiteSpace(request.YouTubeUrl))
        {
            await db.Channel.AddAsync(ChannelEntity.Create(
                member.ID,
                request.YouTubeSID,
                request.YouTubeName,
                request.YouTubeUrl
            ), ct);
        }

        await db.SaveChangesAsync(ct);
    }
}