using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using JobTrackerApi.Services;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Protocols;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;
using Moq;
using Xunit;

namespace JobTrackerApi.Tests;

public sealed class GoogleTokenValidatorTests
{
    [Fact]
    public async Task ValidateAsync_accepts_subject_mapped_to_nameidentifier_claim()
    {
        var config = new ConfigurationBuilder()
            .AddInMemoryCollection(new Dictionary<string, string?>
            {
                ["Auth:GoogleClientId"] = "client-123",
            })
            .Build();

        var signingKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("super-secret-signing-key-super-secret"));
        var oidc = new OpenIdConnectConfiguration();
        oidc.SigningKeys.Add(signingKey);

        var configManager = new Mock<IConfigurationManager<OpenIdConnectConfiguration>>();
        configManager.Setup(x => x.GetConfigurationAsync(It.IsAny<CancellationToken>())).ReturnsAsync(oidc);

        var token = new JwtSecurityTokenHandler().WriteToken(new JwtSecurityToken(
            issuer: "https://accounts.google.com",
            audience: "client-123",
            claims: new[]
            {
                new Claim(JwtRegisteredClaimNames.Sub, "google-subject-1"),
                new Claim("email", "demo@example.com"),
                new Claim("email_verified", "true"),
                new Claim("given_name", "Demo"),
                new Claim("family_name", "User"),
                new Claim("name", "Demo User"),
            },
            expires: DateTime.UtcNow.AddMinutes(10),
            signingCredentials: new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256)));

        var validator = new GoogleTokenValidator(config, configManager.Object);
        var result = await validator.ValidateAsync(token);

        Assert.Equal("google-subject-1", result.Subject);
        Assert.Equal("demo@example.com", result.Email);
        Assert.True(result.EmailVerified);
        Assert.Equal("Demo", result.GivenName);
        Assert.Equal("User", result.FamilyName);
        Assert.Equal("Demo User", result.Name);
    }
}
