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

namespace Application.Features.Api.Forum.CommentReaction.Toggle;

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

        var existing = await db.CommentReaction.FirstOrDefaultAsync(x => x.CommentID == request.CommentID && x.MemberID == request.MemberID, ct);

        // MemberStats 조회 (Like만 카운트) — 1회 쿼리로 giver/receiver 동시 로드
        var memberIDs = comment.MemberID != request.MemberID ? new[] { request.MemberID, comment.MemberID } : [request.MemberID];

        var statsList = await db.MemberStats.Where(x => memberIDs.Contains(x.MemberID)).ToListAsync(ct);

        var giverStats = statsList.FirstOrDefault(x => x.MemberID == request.MemberID);
        var receiverStats = comment.MemberID != request.MemberID ? statsList.FirstOrDefault(x => x.MemberID == comment.MemberID) : null;

        if (existing is not null)
        {
            if (existing.Reaction == request.Reaction)
            {
                if (existing.Reaction == Reaction.Like)
                {
                    comment.Likes--;

                    if (giverStats is not null) { giverStats.LikeGivenCount--; }
                    if (receiverStats is not null) { receiverStats.LikeReceivedCount--; }
                }
                else
                {
                    comment.Dislikes--;
                }

                db.CommentReaction.Remove(existing);
            }
            else
            {
                if (existing.Reaction == Reaction.Like)
                {
                    comment.Likes--;
                    comment.Dislikes++;

                    // Like → Dislike: Like 카운트 감소
                    if (giverStats is not null) { giverStats.LikeGivenCount--; }
                    if (receiverStats is not null) { receiverStats.LikeReceivedCount--; }
                }
                else
                {
                    comment.Dislikes--;
                    comment.Likes++;

                    // Dislike → Like: Like 카운트 증가
                    if (giverStats is not null) { giverStats.LikeGivenCount++; }
                    if (receiverStats is not null) { receiverStats.LikeReceivedCount++; }
                }

                existing.Reaction = request.Reaction;
                existing.UpdatedAt = DateTime.UtcNow;
            }
        }
        else
        {
            var reaction = new Domain.Entities.Forum.Comments.CommentReaction
            {
                BoardID = comment.BoardID,
                PostID = comment.PostID,
                CommentID = request.CommentID,
                MemberID = request.MemberID,
                Reaction = request.Reaction
            };

            await db.CommentReaction.AddAsync(reaction, ct);

            if (request.Reaction == Reaction.Like)
            {
                comment.Likes++;

                if (giverStats is not null) { giverStats.LikeGivenCount++; }
                if (receiverStats is not null) { receiverStats.LikeReceivedCount++; }
            }
            else
            {
                comment.Dislikes++;
            }
        }

        await db.SaveChangesAsync(ct);

        return Result.Success();
    }
}