@using JSMR.UI.Blazor.Services
@using Microsoft.AspNetCore.Components.Routing

@inject SessionState Session
@inject NavigationManager Navigation

@if (!_ready)
{
    <p>Loading...</p>
}
else
{
    @ChildContent
}

@code {
    [Parameter] public RenderFragment? ChildContent { get; set; }

    private bool _ready;

    // Add any routes you want public here.
    // Use absolute-path form (leading slash).
    private static readonly HashSet<string> _allowAnonymous = new(StringComparer.OrdinalIgnoreCase)
    {
        "/login",
        "/login/",   // optional
    };

    protected override async Task OnInitializedAsync()
    {
        Navigation.LocationChanged += OnLocationChanged;

        // One-time refresh at app start
        await Session.RefreshAsync();
        _ready = true;

        await EnforceAsync();
    }

    private async void OnLocationChanged(object? sender, LocationChangedEventArgs e)
    {
        // If your Session can change based on navigation/cookies, you *may* refresh here,
        // but avoid doing it on every navigation unless necessary.
        // await Session.RefreshAsync();

        await EnforceAsync();
    }

    private Task EnforceAsync()
    {
        if (!_ready) return Task.CompletedTask;

        var path = "/" + Navigation.ToBaseRelativePath(Navigation.Uri);
        var qIndex = path.IndexOf('?', StringComparison.Ordinal);
        if (qIndex >= 0) path = path[..qIndex];

        // allow anonymous routes
        if (_allowAnonymous.Contains(path))
            return Task.CompletedTask;

        if (!Session.IsAuthenticated)
        {
            var returnUrl = Uri.EscapeDataString(Navigation.Uri);
            Navigation.NavigateTo($"/login?returnUrl={returnUrl}", forceLoad: false);
        }

        return Task.CompletedTask;
    }

    public void Dispose()
        => Navigation.LocationChanged -= OnLocationChanged;
}