using System.IdentityModel.Tokens.Jwt;
using BackOffice.Common.Utilities;
using Blazored.LocalStorage;

namespace BackOffice.Common.Utilities;

public class AppTokenProvider : ITokenProvider
{
    private readonly ILocalStorageService _localStorage;
    private string _token;

    public AppTokenProvider(ILocalStorageService localStorage)
    {
        _localStorage = localStorage;
    }

    public async Task<string> GetTokenAsync()
    {
        if (_token == null)
        {
            var authorizationToken = await _localStorage.GetItemAsync<string>(GlobalConstants.JwtTokenKey);
            if (!string.IsNullOrEmpty(authorizationToken))
            {
                var raw = authorizationToken.ToString().Replace("Bearer ", "");
                // Don't send expired tokens — they cause 401 on anonymous endpoints like login
                if (IsTokenExpired(raw))
                {
                    await _localStorage.RemoveItemAsync(GlobalConstants.JwtTokenKey);
                    _token = null;
                    return _token;
                }
                _token = raw;
            }
        }
        else if (IsTokenExpired(_token))
        {
            // Cached token has expired since last check
            await _localStorage.RemoveItemAsync(GlobalConstants.JwtTokenKey);
            _token = null;
        }

        return _token;
    }

    private static bool IsTokenExpired(string token)
    {
        try
        {
            var handler = new JwtSecurityTokenHandler();
            var jwt = handler.ReadJwtToken(token);
            // Add 30-second buffer to avoid edge-case race
            return jwt.ValidTo < DateTime.UtcNow.AddSeconds(-30);
        }
        catch
        {
            // Malformed token — treat as expired
            return true;
        }
    }
}