namespace AAIntegration.SimmonsBank.API.Handlers;

using System.Security.Claims;
using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Options;
using AAIntegration.SimmonsBank.API.Services;
using AAIntegration.SimmonsBank.API.Configs;

public class ApiKeyAuthenticationHandler : AuthenticationHandler<ApiKeyAuthenticationOptions>
{
    private readonly ICacheService _cacheService;
    private readonly ILogger<ApiKeyAuthenticationHandler> _logger;

    public ApiKeyAuthenticationHandler (
        IOptionsMonitor<ApiKeyAuthenticationOptions> options,
        ILoggerFactory loggerFactory,
        UrlEncoder encoder,
        ISystemClock clock,
        ICacheService cacheService,
        ILogger<ApiKeyAuthenticationHandler> logger
        ) : base(options, loggerFactory, encoder, clock)
    {
        _cacheService = cacheService;
        _logger = logger;
    }

    protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
    {
        if (!Request.Headers.TryGetValue(ApiKeyAuthenticationOptions.HeaderName, out var apiKey) || apiKey.Count != 1)
        {
            //_logger.LogWarning("An API request was received without the x-api-key header");
            return AuthenticateResult.Fail("Invalid parameters");
        }

        var clientId = _cacheService.GetClientIdFromApiKey(apiKey);

        if (clientId <= 0)
        {
            _logger.LogWarning($"An API request was received with an invalid API key: {apiKey}");
            return AuthenticateResult.Fail("Invalid parameters");
        }

        _logger.BeginScope("{ClientId}", clientId);
        _logger.LogInformation($"Client '{clientId}' authenticated with API Key");

        var claims = new[] { new Claim(ClaimTypes.Name, clientId.ToString()) };
        var identity = new ClaimsIdentity(claims, ApiKeyAuthenticationOptions.DefaultScheme);
        var identities = new List<ClaimsIdentity> { identity };
        var principal = new ClaimsPrincipal(identities);
        var ticket = new AuthenticationTicket(principal, ApiKeyAuthenticationOptions.DefaultScheme);

        return AuthenticateResult.Success(ticket);
    }
}
