using NSubstitute;
using SIGCM2.Application.Abstractions.Persistence;
using SIGCM2.Application.Common;
using SIGCM2.Application.TiposDeIva.List;
using SIGCM2.Domain.Entities;

namespace SIGCM2.Application.Tests.TiposDeIva.List;

public class ListTiposDeIvaQueryHandlerTests
{
    private readonly ITipoDeIvaRepository _repo = Substitute.For<ITipoDeIvaRepository>();
    private readonly ListTiposDeIvaQueryHandler _handler;

    private static TipoDeIva MakeEntity(int id) => TipoDeIva.FromDb(
        id: id, codigo: "IVA_21", descripcion: "IVA 21%", porcentaje: 21m, aplicaIVA: true,
        activo: true, vigenciaDesde: new DateOnly(2024, 1, 1), vigenciaHasta: null,
        predecesorId: null, fechaCreacion: DateTime.UtcNow, fechaModificacion: null);

    public ListTiposDeIvaQueryHandlerTests()
    {
        _handler = new ListTiposDeIvaQueryHandler(_repo);
    }

    [Fact]
    public async Task Handle_WithItems_ReturnsPagedResultWithMappedDtos()
    {
        var items = new List<TipoDeIva> { MakeEntity(1), MakeEntity(2) };
        _repo.ListAsync(Arg.Any<TiposDeIvaQuery>(), Arg.Any<CancellationToken>())
             .Returns(new PagedResult<TipoDeIva>(items, 1, 10, 2));

        var result = await _handler.Handle(new ListTiposDeIvaQuery(1, 10, null, null));

        Assert.Equal(2, result.Items.Count);
        Assert.Equal(2, result.Total);
    }

    [Fact]
    public async Task Handle_EmptyResult_ReturnsPagedResultWithZeroItems()
    {
        _repo.ListAsync(Arg.Any<TiposDeIvaQuery>(), Arg.Any<CancellationToken>())
             .Returns(new PagedResult<TipoDeIva>(new List<TipoDeIva>(), 1, 10, 0));

        var result = await _handler.Handle(new ListTiposDeIvaQuery(1, 10, null, null));

        Assert.Empty(result.Items);
        Assert.Equal(0, result.Total);
    }

    [Fact]
    public async Task Handle_PassesFiltersToRepository()
    {
        _repo.ListAsync(Arg.Any<TiposDeIvaQuery>(), Arg.Any<CancellationToken>())
             .Returns(new PagedResult<TipoDeIva>(new List<TipoDeIva>(), 1, 10, 0));

        await _handler.Handle(new ListTiposDeIvaQuery(2, 5, true, "IVA_21"));

        await _repo.Received(1).ListAsync(
            Arg.Is<TiposDeIvaQuery>(q => q.Page == 2 && q.PageSize == 5 && q.Activo == true && q.Codigo == "IVA_21"),
            Arg.Any<CancellationToken>());
    }
}
