using FluentAssertions;
using Moq;
using TakeoutSaaS.Application.App.Tenants.Handlers;
using TakeoutSaaS.Application.App.Tenants.Queries;
using TakeoutSaaS.Application.Tests.TestUtilities;
using TakeoutSaaS.Domain.Tenants.Enums;
using TakeoutSaaS.Domain.Tenants.Repositories;
using TakeoutSaaS.Shared.Abstractions.Security;
using TakeoutSaaS.Shared.Abstractions.Tenancy;

namespace TakeoutSaaS.Application.Tests.App.Tenants.Handlers;

public sealed class GetUnreadAnnouncementsQueryHandlerTests
{
    [Fact]
    public async Task GivenUnreadAnnouncements_WhenHandle_ThenUsesTenantProviderAndPaginates()
    {
        // Arrange
        var tenantProvider = new Mock<ITenantProvider>();
        tenantProvider.Setup(x => x.GetCurrentTenantId()).Returns(55);

        var currentUserAccessor = new Mock<ICurrentUserAccessor>();
        currentUserAccessor.SetupGet(x => x.UserId).Returns(0);
        currentUserAccessor.SetupGet(x => x.IsAuthenticated).Returns(false);

        var announcements = new List<TakeoutSaaS.Domain.Tenants.Entities.TenantAnnouncement>
        {
            AnnouncementTestData.CreateAnnouncement(1, 55, priority: 1, effectiveFrom: DateTime.UtcNow.AddDays(-1), status: AnnouncementStatus.Published),
            AnnouncementTestData.CreateAnnouncement(2, 55, priority: 3, effectiveFrom: DateTime.UtcNow.AddDays(-2), status: AnnouncementStatus.Published),
            AnnouncementTestData.CreateAnnouncement(3, 55, priority: 2, effectiveFrom: DateTime.UtcNow, status: AnnouncementStatus.Published)
        };

        var announcementRepository = new Mock<ITenantAnnouncementRepository>();
        announcementRepository
            .Setup(x => x.SearchUnreadAsync(
                It.IsAny<long>(),
                It.IsAny<long?>(),
                It.IsAny<AnnouncementStatus?>(),
                It.IsAny<bool?>(),
                It.IsAny<DateTime?>(),
                It.IsAny<CancellationToken>()))
            .ReturnsAsync(announcements);

        var handler = new GetUnreadAnnouncementsQueryHandler(
            announcementRepository.Object,
            tenantProvider.Object,
            currentUserAccessor.Object);

        var query = new GetUnreadAnnouncementsQuery
        {
            Page = 1,
            PageSize = 2
        };

        // Act
        var result = await handler.Handle(query, CancellationToken.None);

        // Assert
        announcementRepository.Verify(x => x.SearchUnreadAsync(
            55,
            null,
            AnnouncementStatus.Published,
            true,
            It.IsAny<DateTime?>(),
            It.IsAny<CancellationToken>()), Times.Once);

        result.Items.Select(x => x.Id).Should().Equal(2, 3);
        result.TotalCount.Should().Be(3);
        result.Page.Should().Be(1);
        result.PageSize.Should().Be(2);
    }
}
