using Application.Abstractions.Messaging;
using Application.Abstractions.Data;
using Application.Abstractions.Cache;
using Domain.Entities.Crypto;
using SharedKernel.Storage;
using Microsoft.EntityFrameworkCore;

namespace Application.Features.Admin.Crypto.List.Create
{
    public sealed class Handler(IAppDbContext db, IFileStorage fileStorage, ICacheService cache) : ICommandHandler<Command>
    {
        public async Task Handle(Command request, CancellationToken ct)
        {
            if (await db.Coin.AnyAsync(c => c.Symbol == request.Symbol.ToUpper(), ct))
            {
                throw new InvalidOperationException($"`{request.Symbol.ToUpper()}`는 이미 등록된 심볼입니다.");
            }

            var coin = Coin.Create(
                request.Symbol,
                request.KorName,
                request.EngName,
                request.Description,
                request.ContractAddress,
                request.WebsiteUrl,
                request.WhitepaperUrl,
                request.TwitterUrl,
                request.TelegramUrl,
                request.IsActive,
                request.IsWarning,
                request.IsNew,
                request.IsDelisted
            );

            await db.Coin.AddAsync(coin, ct);
            await db.SaveChangesAsync(ct);

            FileStoragePath uploadPath = new FileStoragePath(UploadTarget.Upload, UploadFolder.Crypto, coin.ID);
            string[] allowedFileExtensions = [".jpg", ".jpeg", ".png", ".gif", ".webp", ".svg"];

            if (request.LogoImageFile is not null)
            {
                coin.SetLogoImage(
                    (await fileStorage.SaveFileAsync(request.LogoImageFile, uploadPath, allowedFileExtensions, ct))?.Url
                );
            }

            foreach (var categoryID in request.CategoryIDs)
            {
                db.CoinCategoryMap.Add(new CoinCategoryMap { CoinID = coin.ID, CategoryID = categoryID });
            }

            await db.SaveChangesAsync(ct);
            await cache.RemoveByPrefixAsync("crypto:", ct);
        }
    }
}