using FluentAssertions;
using InboxIntel.Application.Abstractions;
using InboxIntel.Application.Search;
using InboxIntel.Domain.Entities;
using InboxIntel.Infrastructure.Persistence;
using InboxIntel.Infrastructure.Search;
using Microsoft.EntityFrameworkCore;
using Xunit;
namespace InboxIntel.IntegrationTests;
///
/// Regression guard for the V-10 pagination clamp: the clamp must live at the
/// user-facing controller boundary, NOT in SearchService — otherwise internal
/// callers (CleanupService resolves targets with pageSize 10000) would be silently
/// capped, breaking bulk cleanup-by-query. This proves the service itself honours a
/// large page.
///
public class SearchPaginationTests
{
private sealed class FakeCurrentUser : ICurrentUser
{
public Guid UserId { get; set; }
public bool IsAuthenticated => UserId != Guid.Empty;
}
[Fact]
public async Task SearchService_does_not_clamp_large_internal_page()
{
var user = Guid.NewGuid();
var opts = new DbContextOptionsBuilder()
.UseInMemoryDatabase(nameof(SearchService_does_not_clamp_large_internal_page)).Options;
using (var seed = new AppDbContext(opts, new FakeCurrentUser()))
{
var sender = new Sender { UserId = user, Address = "sender@example.com", DisplayName = "Sender" };
seed.Senders.Add(sender);
for (var i = 0; i < 250; i++)
seed.Emails.Add(new Email { UserId = user, GmailMessageId = $"m{i}", Subject = $"s{i}", SenderId = sender.Id, Sender = sender });
await seed.SaveChangesAsync();
}
using var ctx = new AppDbContext(opts, new FakeCurrentUser { UserId = user });
// Mirrors how CleanupService resolves targets: a large page via the parser.
var request = GmailQueryParser.Parse(null, page: 1, pageSize: 10_000);
var result = await new SearchService(ctx).SearchAsync(user, request);
result.Items.Should().HaveCount(250); // not capped at 200
result.TotalCount.Should().Be(250);
}
}