using Application.Abstractions.Messaging;
using Application.Abstractions.Data;
using Application.Abstractions.Forum;
using Microsoft.EntityFrameworkCore;
using SharedKernel.Results;

namespace Application.Features.Api.Forum.Comment.Delete;

public sealed class Handler(IAppDbContext db, IBoardPermissionService permissionService) : ICommandHandler<Command, Result>
{
    public async Task<Result> Handle(Command request, CancellationToken ct)
    {
        var comment = await db.Comment.FirstOrDefaultAsync(x => x.ID == request.ID, ct);
        if (comment is null)
        {
            return Result.Failure(Error.NotFound("Comment.NotFound", "댓글을 찾을 수 없습니다."));
        }

        if (comment.MemberID != request.MemberID)
        {
            var reqMember = await db.Member.AsNoTracking().FirstOrDefaultAsync(x => x.ID == request.MemberID, ct);
            if (reqMember is null || !reqMember.IsAdmin)
            {
                var mgr = await permissionService.GetBoardManagerAsync(comment.BoardID, request.MemberID, ct);
                if (mgr is null || !mgr.CanDelete)
                {
                    return Result.Failure(Error.Forbidden("Comment.Forbidden", "삭제 권한이 없습니다."));
                }
            }
        }

        comment.IsDeleted = true;
        comment.DeletedAt = DateTime.UtcNow;

        // Post 댓글 카운트 감소
        var post = await db.Post.FirstOrDefaultAsync(x => x.ID == comment.PostID, ct);
        if (post is not null)
        {
            post.Comments--;
            post.UpdatedAt = DateTime.UtcNow;
        }

        // Board 댓글 카운트 감소
        var board = await db.Board.FirstOrDefaultAsync(x => x.ID == comment.BoardID, ct);
        if (board is not null)
        {
            board.Comments--;
            board.UpdatedAt = DateTime.UtcNow;
        }

        // MemberStats 댓글 수 감소
        var memberStats = await db.MemberStats.FirstOrDefaultAsync(x => x.MemberID == comment.MemberID, ct);
        if (memberStats is not null)
        {
            memberStats.CommentCount--;
        }

        await db.SaveChangesAsync(ct);

        return Result.Success();
    }
}