using NSubstitute;
using TeleWave.Application.Admin.Users.ListUsers;
using TeleWave.Application.Common.Interfaces;
using TeleWave.Application.Common.Models;
using Xunit;

namespace TeleWave.Application.Tests.Admin;

/// <summary>
/// Список пользователей: хендлер только перекладывает параметры запроса в порт — Identity живёт
/// вне <c>IAppDbContext</c>. Проверяется именно перекладка: потерянный фильтр здесь означал бы
/// заблокированных вперемешку с активными.
/// </summary>
public class ListUsersTests
{
    [Fact]
    public async Task PassesEveryFilterToIdentityService()
    {
        var identity = Substitute.For<IIdentityService>();
        var roleId = Guid.NewGuid();
        var page = new PagedList<UserSummaryDto>([], 0, 2, 25);
        identity
            .ListUsersAsync(Arg.Any<UserListFilter>(), Arg.Any<CancellationToken>())
            .Returns(page);

        var result = await new ListUsersQueryHandler(identity).Handle(
            new ListUsersQuery(2, 25, "иван", roleId, IsBlocked: true, Sort: "created", Desc: true),
            CancellationToken.None
        );

        Assert.Same(page, result);
        await identity
            .Received(1)
            .ListUsersAsync(
                new UserListFilter(2, 25, "иван", roleId, true, "created", true),
                Arg.Any<CancellationToken>()
            );
    }

    [Fact]
    public async Task DefaultsSortAndDirection_WhenNotAsked()
    {
        var identity = Substitute.For<IIdentityService>();
        identity
            .ListUsersAsync(Arg.Any<UserListFilter>(), Arg.Any<CancellationToken>())
            .Returns(new PagedList<UserSummaryDto>([], 0, 1, 20));

        await new ListUsersQueryHandler(identity).Handle(
            new ListUsersQuery(1, 20, null, null, null),
            CancellationToken.None
        );

        // Сверяем фильтр целиком, а не по полям: он record, и значение сравнивается по значению —
        // так проверяются и умолчания сортировки, которые запрос не задавал.
        await identity
            .Received(1)
            .ListUsersAsync(
                new UserListFilter(1, 20, null, null, null),
                Arg.Any<CancellationToken>()
            );
    }
}
