using Microsoft.AspNetCore.Mvc;
using NUnit.Framework;
using Sentinel.UnitTests.Helpers;

namespace Sentinel.UnitTests.Sentinel
{
    [TestFixture]
    public class CheckSecurityUnitTests : SentinelTestBase
    {
        [SetUp]
        public override async Task Setup()
        {
            await base.Setup();
        }

        [TestCase(0)]
        [TestCase(1)]
        [TestCase(2)]
        [TestCase(3)]
        [TestCase(4)]
        [TestCase(5)]
        public async Task CheckSecurity_BelowMaxAttempts_ReturnsNull(int accessAttempts)
        {
            //Arrange
            SentinelRepository.AccessAttempts = accessAttempts;

            var fakeController = FakeController.CreateFakeController();

            //Act
            var result = await Sentinel.CheckSecurity(fakeController, default);

            //Assert
            Assert.That(result, Is.Null);
        }

        [Test]
        public async Task CheckSecurity_AboveMaxAttempts_ReturnsUnauthorized()
        {
            //Arragne
            SentinelRepository.AccessAttempts = 6;

            _fakeClock.DateTime = new DateTimeOffset(2022, 9, 23, 12, 06, 45, TimeSpan.Zero);
            var expectedEarliestAttemptTime = new DateTimeOffset(2022, 9, 23, 11, 06, 45, TimeSpan.Zero);

            FakeController fakeController = FakeController.CreateFakeController();

            //Act
            var result = await Sentinel.CheckSecurity(fakeController, default);

            //Assert
            Assert.That(SentinelRepository.IpAddress, Is.EqualTo("143.24.20.36"));
            Assert.That(SentinelRepository.EarliestAttemptTime, Is.EqualTo(expectedEarliestAttemptTime));

            Assert.That(result, Is.Not.Null);
            Assert.That(result, Is.TypeOf<UnauthorizedObjectResult>());
        }

        [Test]
        public async Task CheckSecurityBehindReverseProxy_AboveMaxAttempts_ReturnsUnauthorized()
        {
            //Arragne
            SentinelRepository.AccessAttempts = 6;

            _fakeClock.DateTime = new DateTimeOffset(2022, 9, 23, 12, 06, 45, TimeSpan.Zero);
            var expectedEarliestAttemptTime = new DateTimeOffset(2022, 9, 23, 11, 06, 45, TimeSpan.Zero);

            var fakeController = FakeController.CreateFakeController();
            fakeController.Request.Headers["X-Forwarded-For"] = "80.1.1.50";

            //Act
            var result = await Sentinel.CheckSecurity(fakeController, default);

            //Assert
            //Assert.That(SentinelRepository.IpAddress, Is.EqualTo("143.24.20.36"));
            Assert.That(SentinelRepository.IpAddress, Is.EqualTo("80.1.1.50"));
            Assert.That(SentinelRepository.EarliestAttemptTime, Is.EqualTo(expectedEarliestAttemptTime));

            Assert.That(result, Is.Not.Null);
            Assert.That(result, Is.TypeOf<UnauthorizedObjectResult>());
        }

        [Test]
        public async Task CheckSecurityBehindReverseProxy_BehindReverseProxy_RemovedPortFromIpAddress()
        {
            //Arragne
            SentinelRepository.AccessAttempts = 6;

            _fakeClock.DateTime = new DateTimeOffset(2022, 9, 23, 12, 06, 45, TimeSpan.Zero);
            var expectedEarliestAttemptTime = new DateTimeOffset(2022, 9, 23, 11, 06, 45, TimeSpan.Zero);

            var fakeController = FakeController.CreateFakeController();
            fakeController.Request.Headers["X-Forwarded-For"] = "80.1.1.50:8472";

            //Act
            var result = await Sentinel.CheckSecurity(fakeController, default);

            //Assert
            //Assert.That(SentinelRepository.IpAddress, Is.EqualTo("143.24.20.36"));
            Assert.That(SentinelRepository.IpAddress, Is.EqualTo("80.1.1.50"));
            Assert.That(SentinelRepository.EarliestAttemptTime, Is.EqualTo(expectedEarliestAttemptTime));

            Assert.That(result, Is.Not.Null);
            Assert.That(result, Is.TypeOf<UnauthorizedObjectResult>());
        }
    }
}