using FluentAssertions;
using Microsoft.Extensions.Logging;
using Moq;
using MyService.API.Application.Commands;
using MyService.Domain.AggregatesModel.SampleAggregate;
using MyService.Domain.SeedWork;
using Xunit;

namespace MyService.UnitTests.Application;

/// <summary>
/// EN: Unit tests for CreateSampleCommandHandler.
/// VI: Unit tests cho CreateSampleCommandHandler.
/// </summary>
public class CreateSampleCommandHandlerTests
{
    private readonly Mock<ISampleRepository> _mockRepository;
    private readonly Mock<ILogger<CreateSampleCommandHandler>> _mockLogger;
    private readonly CreateSampleCommandHandler _handler;

    public CreateSampleCommandHandlerTests()
    {
        _mockRepository = new Mock<ISampleRepository>();
        _mockLogger = new Mock<ILogger<CreateSampleCommandHandler>>();

        var mockUnitOfWork = new Mock<IUnitOfWork>();
        mockUnitOfWork.Setup(u => u.SaveEntitiesAsync(It.IsAny<CancellationToken>()))
            .ReturnsAsync(true);

        _mockRepository.SetupGet(r => r.UnitOfWork).Returns(mockUnitOfWork.Object);

        _handler = new CreateSampleCommandHandler(_mockRepository.Object, _mockLogger.Object);
    }

    [Fact]
    public async Task Handle_WithValidCommand_ShouldCreateSampleAndReturnId()
    {
        // Arrange
        var command = new CreateSampleCommand("Test Sample", "Test Description");

        _mockRepository.Setup(r => r.Add(It.IsAny<Sample>()))
            .Returns((Sample s) => s);

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

        // Assert
        result.Should().NotBeNull();
        result.Id.Should().NotBeEmpty();
        _mockRepository.Verify(r => r.Add(It.IsAny<Sample>()), Times.Once);
    }

    [Fact]
    public async Task Handle_WithValidCommand_ShouldCallSaveEntities()
    {
        // Arrange
        var command = new CreateSampleCommand("Test Sample", null);

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

        // Assert
        _mockRepository.Verify(r => r.UnitOfWork.SaveEntitiesAsync(It.IsAny<CancellationToken>()), Times.Once);
    }
}
