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

namespace SIGCM2.Application.Tests.ProductTypes.GetById;

public class GetProductTypeByIdQueryHandlerTests
{
    private readonly IProductTypeRepository _repo = Substitute.For<IProductTypeRepository>();
    private readonly GetProductTypeByIdQueryHandler _handler;

    public GetProductTypeByIdQueryHandlerTests()
    {
        _handler = new GetProductTypeByIdQueryHandler(_repo);
    }

    private static ProductType FullProductType(int id = 5) =>
        new(id, "Clasificados",
            hasDuration: true, requiresText: true, requiresCategory: false, isBundle: false,
            allowImages: true, maxImages: 10, maxImageSizeMB: 2.5m, maxImageWidth: 1920, maxImageHeight: 1080,
            isActive: true,
            fechaCreacion: new DateTime(2026, 1, 10, 0, 0, 0, DateTimeKind.Utc),
            fechaModificacion: new DateTime(2026, 3, 5, 0, 0, 0, DateTimeKind.Utc));

    [Fact]
    public async Task Handle_Found_ReturnsDetailDto()
    {
        _repo.GetByIdAsync(5, Arg.Any<CancellationToken>()).Returns(FullProductType(5));

        var result = await _handler.Handle(new GetProductTypeByIdQuery(5));

        result.Id.Should().Be(5);
        result.Nombre.Should().Be("Clasificados");
    }

    [Fact]
    public async Task Handle_NotFound_ThrowsProductTypeNotFoundException()
    {
        _repo.GetByIdAsync(999, Arg.Any<CancellationToken>()).Returns((ProductType?)null);

        var act = async () => await _handler.Handle(new GetProductTypeByIdQuery(999));

        await act.Should().ThrowAsync<ProductTypeNotFoundException>()
            .Where(e => e.ProductTypeId == 999);
    }

    [Fact]
    public async Task Handle_DetailContainsAllFields()
    {
        _repo.GetByIdAsync(5, Arg.Any<CancellationToken>()).Returns(FullProductType(5));

        var result = await _handler.Handle(new GetProductTypeByIdQuery(5));

        result.HasDuration.Should().BeTrue();
        result.RequiresText.Should().BeTrue();
        result.RequiresCategory.Should().BeFalse();
        result.IsBundle.Should().BeFalse();
        result.AllowImages.Should().BeTrue();
        result.MaxImages.Should().Be(10);
        result.MaxImageSizeMB.Should().Be(2.5m);
        result.MaxImageWidth.Should().Be(1920);
        result.MaxImageHeight.Should().Be(1080);
        result.IsActive.Should().BeTrue();
        result.FechaCreacion.Should().Be(new DateTime(2026, 1, 10, 0, 0, 0, DateTimeKind.Utc));
        result.FechaModificacion.Should().Be(new DateTime(2026, 3, 5, 0, 0, 0, DateTimeKind.Utc));
    }
}
