using System.Security.Claims;
using CartWise.Application.Interfaces;
using CartWise.Infrastructure.Identity;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.DependencyInjection;

namespace CartWise.Web.Tests;

public class HouseholdAuthorizationTests : IClassFixture<CartWiseWebApplicationFactory>
{
    private readonly CartWiseWebApplicationFactory _factory;

    public HouseholdAuthorizationTests(CartWiseWebApplicationFactory factory)
    {
        _factory = factory;
    }

    [Fact]
    public async Task HouseholdMemberPolicy_SucceedsForMemberAndFailsForNonMember()
    {
        using var scope = _factory.Services.CreateScope();
        var services = scope.ServiceProvider;

        var userManager = services.GetRequiredService<UserManager<ApplicationUser>>();
        var householdService = services.GetRequiredService<IHouseholdService>();
        var authorizationService = services.GetRequiredService<IAuthorizationService>();

        var userA = await CreateUserAsync(userManager, "alice@example.com");
        var userB = await CreateUserAsync(userManager, "bob@example.com");

        var householdA = await householdService.CreateHouseholdAsync("Household A", userA.Id);
        Assert.True(householdA.IsSuccess);

        var principalA = CreatePrincipal(userA);
        var principalB = CreatePrincipal(userB);

        var ownResult = await authorizationService.AuthorizeAsync(principalA, householdA.Value!.HouseholdId, "HouseholdMember");
        var crossResult = await authorizationService.AuthorizeAsync(principalB, householdA.Value!.HouseholdId, "HouseholdMember");

        Assert.True(ownResult.Succeeded);
        Assert.False(crossResult.Succeeded);
    }

    private static async Task<ApplicationUser> CreateUserAsync(UserManager<ApplicationUser> userManager, string email)
    {
        var user = new ApplicationUser
        {
            UserName = email,
            Email = email,
            DisplayName = email,
            CreatedUtc = DateTime.UtcNow
        };

        var result = await userManager.CreateAsync(user, "Sup3rSecret!23");
        Assert.True(result.Succeeded);

        return user;
    }

    private static ClaimsPrincipal CreatePrincipal(ApplicationUser user)
    {
        var identity = new ClaimsIdentity([new Claim(ClaimTypes.NameIdentifier, user.Id)], "Test");
        return new ClaimsPrincipal(identity);
    }
}
