using FluentAssertions;
using NSubstitute;
using Knot.Modules.Conversations.Application.Abstractions;
using Knot.Modules.Conversations.Application.Chats.GetOrCreateFavorites;
using Knot.Modules.Conversations.Domain;
using Knot.Modules.Messaging.Domain;
using Knot.Shared.Kernel;
using Xunit;

namespace Knot.Modules.Conversations.UnitTests;

public class GetOrCreateFavoritesCommandHandlerTests
{
    private readonly IChatRepository _chatRepository;
    private readonly IChatsUnitOfWork _unitOfWork;
    private readonly GetOrCreateFavoritesCommandHandler _handler;

    public GetOrCreateFavoritesCommandHandlerTests()
    {
        _chatRepository = Substitute.For<IChatRepository>();
        _unitOfWork = Substitute.For<IChatsUnitOfWork>();
        _handler = new GetOrCreateFavoritesCommandHandler(_chatRepository, _unitOfWork);
    }

    [Fact]
    public async Task Handle_ShouldReturnExistingChat_WhenFavoritesAlreadyExists()
    {
        // Arrange
        var userId = Guid.NewGuid();
        var existingChat = Chat.Create("Избранное", ChatType.Favorites);

        _chatRepository.GetFavoritesAsync(userId, Arg.Any<CancellationToken>())
            .Returns(existingChat);

        var command = new GetOrCreateFavoritesCommand(userId);

        // Act
        var result = await _handler.Handle(command, CancellationToken.None);

        // Assert
        result.IsSuccess.Should().BeTrue();
        result.Value.Should().Be(existingChat.Id);

        _chatRepository.DidNotReceive().Add(Arg.Any<Chat>());
        await _unitOfWork.DidNotReceive().SaveChangesAsync(Arg.Any<CancellationToken>());
    }

    [Fact]
    public async Task Handle_ShouldCreateNewChat_WhenFavoritesDoesNotExist()
    {
        // Arrange
        var userId = Guid.NewGuid();
        _chatRepository.GetFavoritesAsync(userId, Arg.Any<CancellationToken>())
            .Returns((Chat)null!);

        var command = new GetOrCreateFavoritesCommand(userId);

        // Act
        var result = await _handler.Handle(command, CancellationToken.None);

        // Assert
        result.IsSuccess.Should().BeTrue();
        result.Value.Should().NotBeEmpty();

        _chatRepository.Received(1).Add(Arg.Is<Chat>(c =>
            c.Type == ChatType.Favorites &&
            c.Name == "Избранное" &&
            c.Members.Any(m => m.UserId == userId)));

        await _unitOfWork.Received(1).SaveChangesAsync(Arg.Any<CancellationToken>());
    }
}


