using Application.Abstractions.Messaging;
using Application.Abstractions.Data;
using SharedKernel.Storage;
using Microsoft.EntityFrameworkCore;

namespace Application.Features.Admin.MemberGrade.Update
{
    public sealed class Handler(IAppDbContext db, IFileStorage fileStorage) : ICommandHandler<Command>
    {
        public async Task Handle(Command request, CancellationToken ct)
        {
            var memberGrade = await db.MemberGrade.FirstOrDefaultAsync(x => x.ID == request.ID, ct);
            if (memberGrade is null)
            {
                throw new KeyNotFoundException("회원등급을 찾을 수 없습니다.");
            }

            if (memberGrade.KorName != request.KorName && await db.MemberGrade.AnyAsync(x => x.KorName == request.KorName, ct))
            {
                throw new InvalidOperationException($"'{request.KorName}'은(는) 이미 등록된 한글 명입니다.");
            }

            if (memberGrade.EngName != request.EngName && await db.MemberGrade.AnyAsync(x => x.EngName == request.EngName, ct))
            {
                throw new InvalidOperationException($"'{request.EngName}'은(는) 이미 등록된 영문 명입니다.");
            }

            FileStoragePath uploadPath = new(UploadTarget.Upload, UploadFolder.MemberGrade, memberGrade.ID);
            string[] allowedFileExtensions = [".jpg", ".jpeg", ".png", ".gif", ".webp"];
            string? imagePath = memberGrade.Image;

            if (request.IsImageRemove && !string.IsNullOrEmpty(memberGrade.Image))
            {
                fileStorage.DeleteByUrl(memberGrade.Image);
                imagePath = null;
            }

            if (request.ImageFile is not null)
            {
                if (!string.IsNullOrEmpty(memberGrade.Image))
                {
                    fileStorage.DeleteByUrl(memberGrade.Image);
                }

                imagePath = (await fileStorage.SaveFileAsync(request.ImageFile, uploadPath, allowedFileExtensions, ct))?.Url;
            }

            memberGrade.Update(
                request.KorName,
                request.EngName,
                request.Description,
                request.Order,
                imagePath,
                request.TextColor,
                request.RequiredExp,
                request.RequiredAttendance,
                request.IsActive
            );

            await db.SaveChangesAsync(ct);
        }
    }
}
