using Microsoft.Extensions.Logging;

namespace TaxBaik.Web.Client.Components.Admin.Services;

public sealed class AdminSessionBootstrap : IAdminSessionBootstrap
{
    private readonly ITokenStore _tokenStore;
    private readonly ILocalStorageService _localStorage;
    private readonly ILogger<AdminSessionBootstrap> _logger;
    private readonly SemaphoreSlim _gate = new(1, 1);
    private bool _initialized;

    public AdminSessionBootstrap(
        ITokenStore tokenStore,
        ILocalStorageService localStorage,
        ILogger<AdminSessionBootstrap> logger)
    {
        _tokenStore = tokenStore;
        _localStorage = localStorage;
        _logger = logger;
    }

    public async Task EnsureInitializedAsync()
    {
        if (_initialized)
            return;

        await _gate.WaitAsync();
        try
        {
            if (_initialized)
                return;

            await LoadTokensAsync();
            _initialized = true;
        }
        finally
        {
            _gate.Release();
        }
    }

    private async Task LoadTokensAsync()
    {
        try
        {
            var accessToken = await _localStorage.GetItemAsStringAsync("accessToken");
            var refreshToken = await _localStorage.GetItemAsStringAsync("refreshToken");
            var expiryRaw = await _localStorage.GetItemAsStringAsync("tokenExpiry");

            if (!string.IsNullOrWhiteSpace(accessToken))
                _tokenStore.AccessToken = accessToken;

            if (!string.IsNullOrWhiteSpace(refreshToken))
                _tokenStore.RefreshToken = refreshToken;

            if (TryNormalizeExpiryTicks(expiryRaw, out var expiryTicks))
                _tokenStore.TokenExpiryTicks = expiryTicks;
        }
        catch (Exception ex)
        {
            _logger.LogDebug(ex, "Admin session bootstrap failed");
        }
    }

    private static bool TryNormalizeExpiryTicks(string? rawValue, out long ticks)
    {
        ticks = 0;
        if (!long.TryParse(rawValue, out var parsed))
            return false;

        if (parsed > 10_000_000_000_000L && parsed < 100_000_000_000_000_000L)
        {
            ticks = parsed;
            return true;
        }

        if (parsed > 1_000_000_000_000L && parsed < 100_000_000_000_000L)
        {
            ticks = DateTimeOffset.FromUnixTimeMilliseconds(parsed).UtcDateTime.Ticks;
            return true;
        }

        return false;
    }
}
