using NSubstitute;
using SIGCM2.Application.Abstractions.Persistence;
using SIGCM2.Application.Permisos.List;
using SIGCM2.Domain.Entities;

namespace SIGCM2.Application.Tests.Permisos.List;

public class ListPermisosQueryHandlerTests
{
    private readonly IPermisoRepository _repository = Substitute.For<IPermisoRepository>();
    private readonly ListPermisosQueryHandler _handler;

    public ListPermisosQueryHandlerTests()
    {
        _handler = new ListPermisosQueryHandler(_repository);
    }

    private static Permiso MakePermiso(int id, string codigo, string nombre, string modulo) =>
        Permiso.ForRead(id, codigo, nombre, null, modulo, true, DateTime.UtcNow);

    [Fact]
    public async Task Handle_ReturnsDtosProjectedFromRepository()
    {
        _repository.ListAsync().Returns(new List<Permiso>
        {
            MakePermiso(1, "ventas:contado:crear",  "Cargar orden contado",  "ventas"),
            MakePermiso(2, "textos:editar",         "Editar textos",         "textos"),
        });

        var result = await _handler.Handle(new ListPermisosQuery());

        Assert.Equal(2, result.Count);
        Assert.Equal("ventas:contado:crear", result[0].Codigo);
        Assert.Equal("Cargar orden contado", result[0].Nombre);
        Assert.Equal("ventas", result[0].Modulo);
        Assert.Equal("textos:editar", result[1].Codigo);
    }

    [Fact]
    public async Task Handle_WithFullCatalog_Returns18Items()
    {
        var permisos = Enumerable.Range(1, 18)
            .Select(i => MakePermiso(i, $"modulo{i}:accion{i}", $"Permiso {i}", $"modulo{i}"))
            .ToList();
        _repository.ListAsync().Returns(permisos);

        var result = await _handler.Handle(new ListPermisosQuery());

        Assert.Equal(18, result.Count);
    }

    [Fact]
    public async Task Handle_EmptyRepository_ReturnsEmptyList()
    {
        _repository.ListAsync().Returns(new List<Permiso>());

        var result = await _handler.Handle(new ListPermisosQuery());

        Assert.Empty(result);
    }

    [Fact]
    public async Task Handle_NullDescripcion_MappedCorrectly()
    {
        _repository.ListAsync().Returns(new List<Permiso>
        {
            Permiso.ForRead(1, "pauta:limpiar", "Limpieza de pauta", null, "pauta", true, DateTime.UtcNow),
        });

        var result = await _handler.Handle(new ListPermisosQuery());

        Assert.Single(result);
        Assert.Null(result[0].Descripcion);
    }
}
