using NSubstitute;
using SIGCM2.Application.Abstractions.Persistence;
using SIGCM2.Application.TiposDeIva.GetById;
using SIGCM2.Domain.Entities;
using SIGCM2.Domain.Exceptions;

namespace SIGCM2.Application.Tests.TiposDeIva.GetById;

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

    private static TipoDeIva MakeEntity(int id = 1) => 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 GetTipoDeIvaByIdQueryHandlerTests()
    {
        _handler = new GetTipoDeIvaByIdQueryHandler(_repo);
        _repo.GetByIdAsync(1, Arg.Any<CancellationToken>()).Returns(MakeEntity());
    }

    [Fact]
    public async Task Handle_Found_ReturnsDtoWithCorrectId()
    {
        var result = await _handler.Handle(new GetTipoDeIvaByIdQuery(1));

        Assert.Equal(1, result.Id);
    }

    [Fact]
    public async Task Handle_Found_ReturnsDtoWithAllFields()
    {
        var result = await _handler.Handle(new GetTipoDeIvaByIdQuery(1));

        Assert.Equal("IVA_21", result.Codigo);
        Assert.Equal(21m, result.Porcentaje);
        Assert.True(result.Activo);
    }

    [Fact]
    public async Task Handle_NotFound_ThrowsTipoDeIvaNotFoundException()
    {
        _repo.GetByIdAsync(99, Arg.Any<CancellationToken>()).Returns((TipoDeIva?)null);

        await Assert.ThrowsAsync<TipoDeIvaNotFoundException>(
            () => _handler.Handle(new GetTipoDeIvaByIdQuery(99)));
    }
}
