using Microsoft.AspNetCore.Components.Authorization;
using System.Net.Http.Json;
using System.Security.Claims;
using planli.frontend.Models;

namespace planli.frontend.Services;

/// <summary>
/// Determines auth state by calling GET /api/Auth/me (reads the HttpOnly access-token
/// cookie server-side).  Result is cached for the lifetime of the page; login/logout
/// invalidate the cache immediately via <see cref="NotifyUserLogin"/> /
/// <see cref="NotifyUserLogout"/>.
/// </summary>
public class PlanliAuthStateProvider(
    HttpClient     plain,
    RefreshService refreshService) : AuthenticationStateProvider
{
    private ClaimsPrincipal _cached      = new(new ClaimsIdentity());
    private bool            _initialized = false;

    public override async Task<AuthenticationState> GetAuthenticationStateAsync()
    {
        if (_initialized)
            return new AuthenticationState(_cached);

        _initialized = true;

        var me = await FetchMeAsync();

        if (me is null)
        {
            // Access token may have expired — try a silent refresh then retry /me
            if (await refreshService.TryRefreshAsync())
                me = await FetchMeAsync();
        }

        if (me is not null)
            _cached = BuildPrincipal(me);

        return new AuthenticationState(_cached);
    }

    public void NotifyUserLogin(MeResponse me)
    {
        _cached      = BuildPrincipal(me);
        _initialized = true;
        NotifyAuthenticationStateChanged(
            Task.FromResult(new AuthenticationState(_cached)));
    }

    public void NotifyUserLogout()
    {
        _cached      = new ClaimsPrincipal(new ClaimsIdentity());
        _initialized = true;
        NotifyAuthenticationStateChanged(
            Task.FromResult(new AuthenticationState(_cached)));
    }

    // ── Helpers ──────────────────────────────────────────────────────────────────

    private async Task<MeResponse?> FetchMeAsync()
    {
        try
        {
            var res = await plain.GetAsync("api/Auth/me");
            if (res.IsSuccessStatusCode)
                return await res.Content.ReadFromJsonAsync<MeResponse>();
        }
        catch { /* network error — treat as unauthenticated */ }
        return null;
    }

    private static ClaimsPrincipal BuildPrincipal(MeResponse me)
    {
        var claims = new[]
        {
            new Claim("nameid",      me.Id.ToString()),
            new Claim("unique_name", me.Name),
            new Claim("email",       me.Email),
        };
        return new ClaimsPrincipal(new ClaimsIdentity(claims, "cookie"));
    }
}
