using Microsoft.Extensions.Primitives;

namespace Nexus.Api.Services;

public static class RequestAuthorizationHelper
{
    public sealed record AgentHeaderResolution(
        string? AgentId,
        bool HeaderProvided,
        bool IsRecognized,
        bool CredentialVerified,
        bool IdentityHintAuthorized);

    public static bool IsAuthenticatedService(HttpContext httpContext, IConfiguration configuration) =>
        (httpContext.User.Identity?.IsAuthenticated == true &&
         httpContext.User.IsInRole("Service")) ||
        HasValidServiceKey(httpContext, configuration);

    public static bool HasVerifiedAuthentication(HttpContext httpContext, IConfiguration configuration) =>
        httpContext.User.Identity?.IsAuthenticated == true ||
        HasValidServiceKey(httpContext, configuration);

    public static bool IsPrivilegedUser(HttpContext httpContext) =>
        httpContext.User.Identity?.IsAuthenticated == true &&
        (httpContext.User.IsInRole("owner") || httpContext.User.IsInRole("admin"));

    public static bool CanUseAgentIdentityHint(HttpContext httpContext, IConfiguration configuration) =>
        IsAuthenticatedService(httpContext, configuration) ||
        IsPrivilegedUser(httpContext);

    public static async Task<string?> ResolveAllowedAgentHeaderAsync(
        HttpContext httpContext,
        IAgentService agentService,
        IConfiguration configuration,
        CancellationToken ct)
        => (await ResolveAgentHeaderAsync(httpContext, agentService, configuration, ct)).AgentId;

    public static async Task<AgentHeaderResolution> ResolveAgentHeaderAsync(
        HttpContext httpContext,
        IAgentService agentService,
        IConfiguration configuration,
        CancellationToken ct)
    {
        var headerValue = httpContext.Request.Headers["X-Agent-Id"].FirstOrDefault();
        if (string.IsNullOrWhiteSpace(headerValue))
            return new AgentHeaderResolution(
                null,
                HeaderProvided: false,
                IsRecognized: false,
                CredentialVerified: HasVerifiedAuthentication(httpContext, configuration),
                IdentityHintAuthorized: CanUseAgentIdentityHint(httpContext, configuration));

        var allowed = AgentIdentityCatalog.BuildAllowedActorIds(await agentService.GetAllowedAgentIdsAsync(ct));
        var normalized = AgentIdentityCatalog.NormalizeActorId(headerValue, allowed);
        var credentialVerified = HasVerifiedAuthentication(httpContext, configuration);
        var identityHintAuthorized = CanUseAgentIdentityHint(httpContext, configuration);
        return new AgentHeaderResolution(
            identityHintAuthorized ? normalized : null,
            HeaderProvided: true,
            IsRecognized: normalized is not null,
            CredentialVerified: credentialVerified,
            IdentityHintAuthorized: identityHintAuthorized);
    }

    public static bool HasValidServiceKey(HttpContext httpContext, IConfiguration configuration)
    {
        var configuredApiKey = configuration["NexusApiKey"];
        if (string.IsNullOrWhiteSpace(configuredApiKey))
            return false;

        if (!httpContext.Request.Headers.TryGetValue("X-Nexus-Api-Key", out StringValues providedKey))
            return false;

        return string.Equals(configuredApiKey, providedKey.FirstOrDefault(), StringComparison.Ordinal);
    }
}
