using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Knot.Shared.Kernel;
using Knot.Contracts.Conversations.Domain;
using Knot.Contracts.Conversations.Application.Abstractions;
using MediatR;
using System.Linq;

namespace Knot.Modules.Conversations.Application.Chats.Members;

public record AddMembersCommand(Guid ChatId, Guid UserId, List<Guid> UserIdsToAdd) : ICommand<Guid>;

internal sealed class AddMembersCommandHandler : ICommandHandler<AddMembersCommand, Guid>
{
    private readonly IChatRepository _chatRepository;
    private readonly IChatsUnitOfWork _uow;

    public AddMembersCommandHandler(IChatRepository chatRepository, IChatsUnitOfWork uow)
    {
        _chatRepository = chatRepository;
        _uow = uow;
    }

    public async Task<Result<Guid>> Handle(AddMembersCommand request, CancellationToken cancellationToken)
    {
        var chat = await _chatRepository.GetByIdAsync(request.ChatId, cancellationToken);
        if (chat == null || !chat.Members.Any(m => m.UserId == request.UserId))
        {
            return Result.Failure<Guid>(ChatErrors.ChatNotFound);
        }

        foreach (var userId in request.UserIdsToAdd)
        {
            chat.AddMember(userId);
        }
        _chatRepository.Update(chat);
        await _uow.SaveChangesAsync(cancellationToken);

        return Result.Success(request.ChatId);
    }
}

public record RemoveMemberCommand(Guid ChatId, Guid UserId, Guid UserIdToRemove) : ICommand<Guid>;

internal sealed class RemoveMemberCommandHandler : ICommandHandler<RemoveMemberCommand, Guid>
{
    private readonly IChatRepository _chatRepository;
    private readonly IChatsUnitOfWork _uow;

    public RemoveMemberCommandHandler(IChatRepository chatRepository, IChatsUnitOfWork uow)
    {
        _chatRepository = chatRepository;
        _uow = uow;
    }

    public async Task<Result<Guid>> Handle(RemoveMemberCommand request, CancellationToken cancellationToken)
    {
        var chat = await _chatRepository.GetByIdAsync(request.ChatId, cancellationToken);
        if (chat == null || !chat.Members.Any(m => m.UserId == request.UserId))
        {
            return Result.Failure<Guid>(ChatErrors.ChatNotFound);
        }

        chat.RemoveMember(request.UserIdToRemove);
        _chatRepository.Update(chat);
        await _uow.SaveChangesAsync(cancellationToken);

        return Result.Success(request.ChatId);
    }
}

