﻿using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text.Json;
using Blazored.LocalStorage;
using Microsoft.AspNetCore.Components.Authorization;

namespace BackOffice.Common.Utilities;

public class ApiAuthenticationStateProvider : AuthenticationStateProvider
{
    private readonly ILocalStorageService _localStorage;

    public ApiAuthenticationStateProvider(ILocalStorageService localStorage)
    {
        _localStorage = localStorage;
    }
    public override async Task<AuthenticationState> GetAuthenticationStateAsync()
    {
        try
        {

            var savedToken = await _localStorage.GetItemAsync<string>(GlobalConstants.JwtTokenKey);
            if (string.IsNullOrWhiteSpace(savedToken))
            {
                return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
            }
            var handler = new JwtSecurityTokenHandler();
            var token = handler.ReadJwtToken(savedToken);

            // Parse the token payload to handle array-based roles
            var claims = new List<Claim>();
            
            foreach (var claim in token.Claims)
            {
                // Handle role claims specially to support multiple roles
                if (claim.Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" || 
                    claim.Type == ClaimTypes.Role || 
                    claim.Type == "role")
                {
                    // Check if the value is a JSON array
                    if (claim.Value.TrimStart().StartsWith("["))
                    {
                        try
                        {
                            var roles = JsonSerializer.Deserialize<string[]>(claim.Value);
                            if (roles != null)
                            {
                                foreach (var role in roles)
                                {
                                    claims.Add(new Claim(ClaimTypes.Role, role));
                                }
                            }
                        }
                        catch
                        {
                            // If parsing fails, add as single claim
                            claims.Add(new Claim(ClaimTypes.Role, claim.Value));
                        }
                    }
                    else
                    {
                        // Single role value
                        claims.Add(new Claim(ClaimTypes.Role, claim.Value));
                    }
                }
                else
                {
                    claims.Add(claim);
                }
            }

            var authenticationState = new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity(claims, "jwt")));

            return authenticationState;
        }
        catch
        {
            return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
        }
    }

    public void MarkUserAsAuthenticated(string email)
    {
        var authenticatedUser = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, email) }, "apiauth"));
        var authState = Task.FromResult(new AuthenticationState(authenticatedUser));
        NotifyAuthenticationStateChanged(authState);
    }

    public void MarkUserAsLoggedOut()
    {
        var anonymousUser = new ClaimsPrincipal(new ClaimsIdentity());
        var authState = Task.FromResult(new AuthenticationState(anonymousUser));
        NotifyAuthenticationStateChanged(authState);
    }   
}
