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

namespace Application.Features.Admin.Forum.BoardMeta.Update;

public sealed class Handler(IAppDbContext db, IEditorImageService editorImage, ICacheService cache) : ICommandHandler<Command>
{
    public async Task Handle(Command request, CancellationToken ct)
    {
        var meta = await db.BoardMeta.FirstOrDefaultAsync(x => x.ID == request.ID && x.BoardID == request.BoardID, ct) ?? throw new KeyNotFoundException("게시판 설정을 찾을 수 없습니다.");

        if (request.List is not null)
        {
            meta.List = request.List;
            meta.List.HeaderContent = await SaveBytesAsync(request.BoardID, request.List.HeaderContent, UploadAddition.ListHeaderContent, ct);
            meta.List.FooterContent = await SaveBytesAsync(request.BoardID, request.List.FooterContent, UploadAddition.ListFooterContent, ct);
        }

        if (request.View is not null)
        {
            meta.View = request.View;
        }

        if (request.Write is not null)
        {
            meta.Write = request.Write;
            meta.Write.HeaderContent = await SaveBytesAsync(request.BoardID, request.Write.HeaderContent, UploadAddition.WriteHeaderContent, ct);
            meta.Write.FooterContent = await SaveBytesAsync(request.BoardID, request.Write.FooterContent, UploadAddition.WriteFooterContent, ct);
        }

        if (request.Comment is not null)
        {
            meta.Comment = request.Comment;
        }

        if (request.General is not null)
        {
            meta.General = request.General;
        }

        if (request.Permission is not null)
        {
            meta.Permission = request.Permission;
        }

        if (request.Notify is not null)
        {
            meta.Notify = request.Notify;
        }

        if (request.NotifyTemplate is not null)
        {
            meta.NotifyTemplate = request.NotifyTemplate;
            meta.NotifyTemplate.PostWriteEmailNotifyContent = await SaveBytesAsync(request.BoardID, request.NotifyTemplate.PostWriteEmailNotifyContent, UploadAddition.PostWriteEmailNotifyContent, ct);
            meta.NotifyTemplate.CommentWriteEmailNotifyContent = await SaveBytesAsync(request.BoardID, request.NotifyTemplate.CommentWriteEmailNotifyContent, UploadAddition.CommentWriteEmailNotifyContent, ct);
            meta.NotifyTemplate.ReplyWriteEmailNotifyContent = await SaveBytesAsync(request.BoardID, request.NotifyTemplate.ReplyWriteEmailNotifyContent, UploadAddition.ReplyWriteEmailNotifyContent, ct);
        }

        if (request.Exp is not null)
        {
            meta.Exp = request.Exp;
        }

        await db.SaveChangesAsync(ct);
        await cache.RemoveAsync(CacheKeys.BoardMeta(request.BoardID), ct);
    }

    private async Task<string?> SaveBytesAsync(int boardID, string? html, UploadAddition addition, CancellationToken ct = default)
    {
        var path = new FileStoragePath(UploadTarget.Editor, UploadFolder.Post, boardID, addition);

        return await editorImage.UploadAsync(html, path, ct);
    }
}