using Indotalent.Data.Entities;
using Indotalent.Infrastructure.Authentication.Identity;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.Server;
using Microsoft.AspNetCore.Identity;
using System.Security.Claims;

internal sealed class IdentityRevalidatingAuthenticationStateProvider : RevalidatingServerAuthenticationStateProvider
{
    private readonly IServiceScopeFactory _scopeFactory;
    private readonly IHttpContextAccessor _httpContextAccessor;
    private readonly TokenProvider _tokenProvider;

    public IdentityRevalidatingAuthenticationStateProvider(
        ILoggerFactory loggerFactory,
        IServiceScopeFactory scopeFactory,
        IHttpContextAccessor httpContextAccessor,
        TokenProvider tokenProvider)
        : base(loggerFactory)
    {
        _scopeFactory = scopeFactory;
        _httpContextAccessor = httpContextAccessor;
        _tokenProvider = tokenProvider;

        var context = httpContextAccessor.HttpContext;
        if (context != null)
        {
            var token = context.Request.Cookies["X-Auth-Token"];
            var refreshToken = context.Request.Cookies["X-Refresh-Token"];
            if (!string.IsNullOrEmpty(token))
            {
                _tokenProvider.Token = token;
            }
            if (!string.IsNullOrEmpty(refreshToken))
            {
                _tokenProvider.RefreshToken = refreshToken;
            }
        }
    }

    protected override TimeSpan RevalidationInterval => TimeSpan.FromMinutes(30);

    protected override async Task<bool> ValidateAuthenticationStateAsync(
        AuthenticationState authenticationState, CancellationToken cancellationToken)
    {
        await using var scopeAsync = _scopeFactory.CreateAsyncScope();
        var userManager = scopeAsync.ServiceProvider.GetRequiredService<UserManager<ApplicationUser>>();
        return await ValidateSecurityStampAsync(userManager, authenticationState.User);
    }

    private async Task<bool> ValidateSecurityStampAsync(UserManager<ApplicationUser> userManager, ClaimsPrincipal principal)
    {
        var user = await userManager.GetUserAsync(principal);
        return user != null;
    }
}