using System.Security.Claims;
using JobTrackerApi.Controllers;
using JobTrackerApi.Models;
using JobTrackerApi.Tests.TestSupport;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Moq;
using Xunit;

namespace JobTrackerApi.Tests;

public sealed class NotificationSettingsControllerTests
{
    [Fact]
    public async Task Get_returns_the_authenticated_users_preference()
    {
        var user = new ApplicationUser { Id = "user-1", EmailFollowUpRemindersEnabled = false };
        var users = TestHostFactory.CreateUserManager(user);
        users.Setup(x => x.GetUserAsync(It.IsAny<ClaimsPrincipal>())).ReturnsAsync(user);

        var result = await CreateController(users).Get();

        var ok = Assert.IsType<OkObjectResult>(result.Result);
        var settings = Assert.IsType<NotificationSettingsController.NotificationSettingsDto>(ok.Value);
        Assert.False(settings.EmailFollowUpRemindersEnabled);
    }

    [Fact]
    public async Task Put_persists_the_authenticated_users_preference()
    {
        var user = new ApplicationUser { Id = "user-1", EmailFollowUpRemindersEnabled = true };
        var users = TestHostFactory.CreateUserManager(user);
        users.Setup(x => x.GetUserAsync(It.IsAny<ClaimsPrincipal>())).ReturnsAsync(user);
        users.Setup(x => x.UpdateAsync(user)).ReturnsAsync(IdentityResult.Success);

        var result = await CreateController(users).Put(new(false));

        var ok = Assert.IsType<OkObjectResult>(result.Result);
        var settings = Assert.IsType<NotificationSettingsController.NotificationSettingsDto>(ok.Value);
        Assert.False(settings.EmailFollowUpRemindersEnabled);
        users.Verify(x => x.UpdateAsync(It.Is<ApplicationUser>(candidate => !candidate.EmailFollowUpRemindersEnabled)), Times.Once);
    }

    [Fact]
    public async Task Put_does_not_update_when_the_request_has_no_authenticated_user()
    {
        var users = TestHostFactory.CreateUserManager();
        users.Setup(x => x.GetUserAsync(It.IsAny<ClaimsPrincipal>())).ReturnsAsync((ApplicationUser?)null);

        var result = await CreateController(users).Put(new(false));

        Assert.IsType<UnauthorizedResult>(result.Result);
        users.Verify(x => x.UpdateAsync(It.IsAny<ApplicationUser>()), Times.Never);
    }

    private static NotificationSettingsController CreateController(Mock<UserManager<ApplicationUser>> users) => new(users.Object)
    {
        ControllerContext = new ControllerContext
        {
            HttpContext = new DefaultHttpContext
            {
                User = new ClaimsPrincipal(new ClaimsIdentity([new Claim(ClaimTypes.NameIdentifier, "user-1")], "local"))
            }
        }
    };
}
