using System.Security.Claims;
using Microsoft.AspNetCore.Http;

namespace SpaceGame.Api.Auth.Simulation;

public sealed class HttpContextPlayerIdentityResolver(IHttpContextAccessor httpContextAccessor) : IPlayerIdentityResolver
{
    public const string EffectivePlayerHeaderName = "X-Act-As-Player-Id";

    public Guid? GetCurrentPlayerId()
    {
        var subject = httpContextAccessor.HttpContext?.User.FindFirstValue(ClaimTypes.NameIdentifier)
          ?? httpContextAccessor.HttpContext?.User.FindFirstValue("sub");
        return Guid.TryParse(subject, out var playerId) ? playerId : null;
    }

    public Guid GetRequiredPlayerId() =>
      GetCurrentPlayerId() ?? throw new InvalidOperationException("Authenticated player identity is required.");

    public Guid? GetEffectivePlayerId()
    {
        var currentPlayerId = GetCurrentPlayerId();
        if (!CanAccessGm())
        {
            return currentPlayerId;
        }

        var requestedIdentity = httpContextAccessor.HttpContext?.Request.Headers[EffectivePlayerHeaderName].FirstOrDefault();
        return Guid.TryParse(requestedIdentity, out var effectivePlayerId) ? effectivePlayerId : currentPlayerId;
    }

    public Guid GetRequiredEffectivePlayerId() =>
      GetEffectivePlayerId() ?? throw new InvalidOperationException("Authenticated player identity is required.");

    public bool CanAccessGm()
    {
        var user = httpContextAccessor.HttpContext?.User;
        return user?.IsInRole("gm") == true || user?.IsInRole("admin") == true;
    }
}
