using System.Security.Claims;
using System.Text.Encodings.Web;
using System.Text.Json;
using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace WorkClub.Tests.Integration.Infrastructure;

public class TestAuthHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
    public TestAuthHandler(
        IOptionsMonitor<AuthenticationSchemeOptions> options,
        ILoggerFactory logger,
        UrlEncoder encoder)
        : base(options, logger, encoder)
    {
    }

    protected override Task<AuthenticateResult> HandleAuthenticateAsync()
    {
        // Support explicit unauthenticated test scenarios
        var unauthenticatedHeader = Context.Request.Headers["X-Test-Unauthenticated"].ToString();
        if (!string.IsNullOrEmpty(unauthenticatedHeader) && unauthenticatedHeader.Equals("true", StringComparison.OrdinalIgnoreCase))
        {
            return Task.FromResult(AuthenticateResult.NoResult());
        }

        var clubsClaim = Context.Request.Headers["X-Test-Clubs"].ToString();
        var emailClaim = Context.Request.Headers["X-Test-Email"].ToString();
        var userIdClaim = Context.Request.Headers["X-Test-UserId"].ToString();
        var clubRolesJson = Context.Request.Headers["X-Test-ClubRoles"].ToString();
        var realmAccessClaim = Context.Request.Headers["X-Test-Realm-Access"].ToString();

        // If no test auth headers are present, return NoResult (unauthenticated)
        if (string.IsNullOrEmpty(emailClaim) && string.IsNullOrEmpty(userIdClaim) && string.IsNullOrEmpty(clubsClaim) && string.IsNullOrEmpty(realmAccessClaim))
        {
            return Task.FromResult(AuthenticateResult.NoResult());
        }

        var resolvedEmail = string.IsNullOrEmpty(emailClaim) ? "test@test.com" : emailClaim;

        var claims = new List<Claim>
        {
            new Claim(ClaimTypes.NameIdentifier, "test-user"),
            new Claim("sub", string.IsNullOrEmpty(userIdClaim) ? Guid.NewGuid().ToString() : userIdClaim),
            new Claim(ClaimTypes.Email, resolvedEmail),
            new Claim("preferred_username", resolvedEmail),
        };
        
        if (!string.IsNullOrEmpty(realmAccessClaim))
        {
            claims.Add(new Claim("realm_access", realmAccessClaim, ClaimValueTypes.String));
        }

        if (!string.IsNullOrEmpty(clubsClaim))
        {
            claims.Add(new Claim("clubs", clubsClaim));
        }

        // Parse tenant-specific role from X-Test-ClubRoles if provided
        if (!string.IsNullOrEmpty(clubRolesJson))
        {
            var tenantId = Context.Request.Headers["X-Tenant-Id"].ToString();
            if (!string.IsNullOrEmpty(tenantId))
            {
                try
                {
                    var clubRoles = JsonSerializer.Deserialize<Dictionary<string, string>>(clubRolesJson);
                    if (clubRoles != null)
                    {
                        var tenantRole = clubRoles.FirstOrDefault(kvp => 
                            kvp.Key.Equals(tenantId, StringComparison.OrdinalIgnoreCase)).Value;
                        
                        if (!string.IsNullOrEmpty(tenantRole))
                        {
                            claims.Add(new Claim(ClaimTypes.Role, tenantRole));
                        }
                    }
                }
                catch (JsonException)
                {
                    // Invalid JSON in X-Test-ClubRoles header, proceed without role claim
                }
            }
        }

        var identity = new ClaimsIdentity(claims, "Test");
        var principal = new ClaimsPrincipal(identity);
        var ticket = new AuthenticationTicket(principal, "Test");

        return Task.FromResult(AuthenticateResult.Success(ticket));
    }
}
