using e_suite.API.Common.models;
using eSuite.API.Controllers;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Moq;
using NUnit.Framework;
using System.Text.Json;

namespace eSuite.API.UnitTests.Controllers.AccountControllerUnitTests;

[TestFixture]
public class LoginGetUnitTests : AccountControllerTestBase
{
    [SetUp]
    public override async Task Setup()
    {
        await base.Setup();
    }

    [Test]
    public async Task LoginGet_WhenLoginNotPresent_ReturnsLoginViewWithEmptyModel()
    {
        //Arrange
        _cookieManagerMock.Setup(x => x.GetSsoIdFromSsoIdCookie(It.IsAny<HttpRequest>())).ReturnsAsync(() => null);

        Login? login = null;

        //Act
        var response = await _accountController.LoginGet(login, CancellationToken.None);

        //Assert
        Assert.That(response, Is.TypeOf<PartialViewResult>());
        var viewResult = response as PartialViewResult;
        Assert.That(viewResult?.ViewName, Is.EqualTo("Login"));
        Assert.That(viewResult?.Model, Is.TypeOf<Login>());

        var actualLogin = viewResult?.Model as Login;
        Assert.That(actualLogin, Is.Not.Null);
        Assert.That(actualLogin?.Email, Is.EqualTo(string.Empty));
        Assert.That(actualLogin?.ForgotPassword, Is.EqualTo(false));
        Assert.That(actualLogin?.Password, Is.EqualTo(string.Empty));
        Assert.That(actualLogin?.RequestTfaRemoval, Is.EqualTo(false));
        Assert.That(actualLogin?.SecurityCode, Is.EqualTo(string.Empty));
    }

    [Test]
    public async Task LoginGet_WhenLoginIncluded_ReturnsLoginViewWithCorrectModel()
    {
        //Arrange
        _cookieManagerMock.Setup(x => x.GetSsoIdFromSsoIdCookie(It.IsAny<HttpRequest>())).ReturnsAsync(() => null);

        Login? login = new Login
        {
            Email = "TestUser@Test.test"
        };

        //Act
        var response = await _accountController.LoginGet(login, CancellationToken.None);

        //Assert
        Assert.That(response, Is.TypeOf<PartialViewResult>());
        var viewResult = response as PartialViewResult;
        Assert.That(viewResult?.ViewName, Is.EqualTo("Login"));
        Assert.That(viewResult?.Model, Is.TypeOf<Login>());

        var actualLogin = viewResult?.Model as Login;
        Assert.That(actualLogin, Is.EqualTo(login));
    }

    [Test]
    public async Task LoginGet_WhenSsoIdCookieExists_RedirectsToSsoLoginUrl()
    {
        // Arrange
        Login? login = null;

        var ssoProviderId = 1;
        var ssoUrl = "http://test.test/login";

        _cookieManagerMock
            .Setup(x => x.GetSsoIdFromSsoIdCookie(It.IsAny<HttpRequest>()))
            .ReturnsAsync(ssoProviderId);

        _singleSignOnMock
            .Setup(x => x.StartSingleSignOn(ssoProviderId, It.IsAny<CancellationToken>()))
            .ReturnsAsync(ssoUrl);

        // Act
        var response = await _accountController.LoginGet(login, CancellationToken.None);

        // Assert
        Assert.That(response, Is.TypeOf<OkObjectResult>());

        var json = response as OkObjectResult;
        Assert.That(json?.Value, Is.Not.Null);

        var payload = json!.Value as Redirect;
        Assert.That(payload.RedirectTo, Is.EqualTo(ssoUrl));

        _cookieManagerMock.Verify(
            x => x.DeleteSsoIdCookie(It.IsAny<HttpResponse>()),
            Times.Once);
    }
}