using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using MongoDB.Driver;
using Moq;
using QRRapidoApp.Data;
using QRRapidoApp.Models;
using QRRapidoApp.Services;
using Xunit;

namespace QRRapidoApp.Tests.Services
{
    public class AdDisplayServiceTests
    {
        private readonly Mock<IUserService> _userServiceMock;
        private readonly Mock<MongoDbContext> _contextMock;
        private readonly Mock<IConfiguration> _configMock;
        private readonly Mock<ILogger<AdDisplayService>> _loggerMock;
        private readonly Mock<IMongoCollection<AdFreeSession>> _sessionCollectionMock;
        private readonly AdDisplayService _service;

        public AdDisplayServiceTests()
        {
            _userServiceMock = new Mock<IUserService>();
            _contextMock = new Mock<MongoDbContext>(Mock.Of<IMongoClient>(), Mock.Of<IConfiguration>());
            _configMock = new Mock<IConfiguration>();
            _loggerMock = new Mock<ILogger<AdDisplayService>>();
            _sessionCollectionMock = new Mock<IMongoCollection<AdFreeSession>>();

            _contextMock.Setup(c => c.AdFreeSessions).Returns(_sessionCollectionMock.Object);

            _service = new AdDisplayService(
                _userServiceMock.Object,
                _contextMock.Object,
                _configMock.Object,
                _loggerMock.Object
            );
        }

        [Fact]
        public async Task ShouldShowAds_WithAnonymousUser_ShouldReturnTrue()
        {
            // Arrange
            string? userId = null;

            // Act
            var result = await _service.ShouldShowAds(userId);

            // Assert
            Assert.True(result);
        }

        [Fact]
        public async Task ShouldShowAds_WithPremiumUser_ShouldReturnFalse()
        {
            // Arrange
            var userId = "test-user-id";
            var user = new User
            {
                Id = userId,
                IsPremium = true,
                PremiumExpiresAt = DateTime.UtcNow.AddDays(30)
            };

            _userServiceMock.Setup(s => s.GetUserAsync(userId))
                           .ReturnsAsync(user);

            // Act
            var result = await _service.ShouldShowAds(userId);

            // Assert
            Assert.False(result);
        }

        [Fact]
        public async Task ShouldShowAds_WithExpiredPremiumUser_ShouldReturnTrue()
        {
            // Arrange
            var userId = "test-user-id";
            var user = new User
            {
                Id = userId,
                IsPremium = true,
                PremiumExpiresAt = DateTime.UtcNow.AddDays(-1) // Expired
            };

            _userServiceMock.Setup(s => s.GetUserAsync(userId))
                           .ReturnsAsync(user);

            var cursor = new Mock<IAsyncCursor<AdFreeSession>>();
            cursor.Setup(_ => _.Current).Returns(new List<AdFreeSession>());
            cursor.SetupSequence(_ => _.MoveNext(It.IsAny<CancellationToken>()))
                  .Returns(false);
            cursor.SetupSequence(_ => _.MoveNextAsync(It.IsAny<CancellationToken>()))
                  .ReturnsAsync(false);

            _sessionCollectionMock.Setup(c => c.FindAsync(
                It.IsAny<FilterDefinition<AdFreeSession>>(),
                It.IsAny<FindOptions<AdFreeSession>>(),
                It.IsAny<CancellationToken>()))
                .ReturnsAsync(cursor.Object);

            // Act
            var result = await _service.ShouldShowAds(userId);

            // Assert
            Assert.True(result);
        }

        [Fact]
        public async Task ShouldShowAds_WithActiveAdFreeSession_ShouldReturnFalse()
        {
            // Arrange
            var userId = "test-user-id";
            var user = new User
            {
                Id = userId,
                IsPremium = false
            };

            var activeSession = new AdFreeSession
            {
                UserId = userId,
                IsActive = true,
                ExpiresAt = DateTime.UtcNow.AddDays(1)
            };

            _userServiceMock.Setup(s => s.GetUserAsync(userId))
                           .ReturnsAsync(user);

            var cursor = new Mock<IAsyncCursor<AdFreeSession>>();
            cursor.Setup(_ => _.Current).Returns(new List<AdFreeSession> { activeSession });
            cursor.SetupSequence(_ => _.MoveNext(It.IsAny<CancellationToken>()))
                  .Returns(true)
                  .Returns(false);
            cursor.SetupSequence(_ => _.MoveNextAsync(It.IsAny<CancellationToken>()))
                  .ReturnsAsync(true)
                  .ReturnsAsync(false);

            _sessionCollectionMock.Setup(c => c.FindAsync(
                It.IsAny<FilterDefinition<AdFreeSession>>(),
                It.IsAny<FindOptions<AdFreeSession>>(),
                It.IsAny<CancellationToken>()))
                .ReturnsAsync(cursor.Object);

            // Act
            var result = await _service.ShouldShowAds(userId);

            // Assert
            Assert.False(result);
        }

        // TESTE REMOVIDO: GetAdFreeTimeRemaining_WithPremiumUser_ShouldReturnMaxValue - método não existe mais

        // TESTES REMOVIDOS: GetAdFreeTimeRemaining - método não existe mais

        [Fact]
        public async Task HasValidPremiumSubscription_WithValidPremium_ShouldReturnTrue()
        {
            // Arrange
            var userId = "test-user-id";
            var user = new User
            {
                Id = userId,
                IsPremium = true,
                PremiumExpiresAt = DateTime.UtcNow.AddDays(30)
            };

            _userServiceMock.Setup(s => s.GetUserAsync(userId))
                           .ReturnsAsync(user);

            // Act
            var result = await _service.HasValidPremiumSubscription(userId);

            // Assert
            Assert.True(result);
        }

        [Fact]
        public async Task HasValidPremiumSubscription_WithExpiredPremium_ShouldReturnFalse()
        {
            // Arrange
            var userId = "test-user-id";
            var user = new User
            {
                Id = userId,
                IsPremium = true,
                PremiumExpiresAt = DateTime.UtcNow.AddDays(-1) // Expired
            };

            _userServiceMock.Setup(s => s.GetUserAsync(userId))
                           .ReturnsAsync(user);

            // Act
            var result = await _service.HasValidPremiumSubscription(userId);

            // Assert
            Assert.False(result);
        }

        [Fact]
        public async Task GetAdFreeStatusAsync_WithPremiumUser_ShouldReturnPremium()
        {
            // Arrange
            var userId = "test-user-id";
            var user = new User
            {
                Id = userId,
                IsPremium = true,
                PremiumExpiresAt = DateTime.UtcNow.AddDays(30)
            };

            _userServiceMock.Setup(s => s.GetUserAsync(userId))
                           .ReturnsAsync(user);

            // Act
            var result = await _service.GetAdFreeStatusAsync(userId);

            // Assert
            Assert.Equal("Premium", result);
        }

        [Fact]
        public async Task GetAdFreeStatusAsync_WithActiveSession_ShouldReturnSessionType()
        {
            // Arrange
            var userId = "test-user-id";
            var user = new User
            {
                Id = userId,
                IsPremium = false
            };

            var activeSession = new AdFreeSession
            {
                UserId = userId,
                IsActive = true,
                ExpiresAt = DateTime.UtcNow.AddDays(1),
                SessionType = "Login"
            };

            _userServiceMock.Setup(s => s.GetUserAsync(userId))
                           .ReturnsAsync(user);

            var cursor = new Mock<IAsyncCursor<AdFreeSession>>();
            cursor.Setup(_ => _.Current).Returns(new List<AdFreeSession> { activeSession });
            cursor.SetupSequence(_ => _.MoveNext(It.IsAny<CancellationToken>()))
                  .Returns(true)
                  .Returns(false);
            cursor.SetupSequence(_ => _.MoveNextAsync(It.IsAny<CancellationToken>()))
                  .ReturnsAsync(true)
                  .ReturnsAsync(false);

            _sessionCollectionMock.Setup(c => c.FindAsync(
                It.IsAny<FilterDefinition<AdFreeSession>>(),
                It.IsAny<FindOptions<AdFreeSession>>(),
                It.IsAny<CancellationToken>()))
                .ReturnsAsync(cursor.Object);

            // Act
            var result = await _service.GetAdFreeStatusAsync(userId);

            // Assert
            Assert.Equal("Login", result);
        }
    }
}