using System.Security.Claims;
using Microsoft.AspNetCore.Authentication;
using Microsoft.EntityFrameworkCore;
using WorkClub.Domain.Enums;
using WorkClub.Infrastructure.Data;

namespace WorkClub.Api.Auth;

public class ClubRoleClaimsTransformation : IClaimsTransformation
{
    private readonly IHttpContextAccessor _httpContextAccessor;
    private readonly AppDbContext _context;

    public ClubRoleClaimsTransformation(
        IHttpContextAccessor httpContextAccessor,
        AppDbContext context)
    {
        _httpContextAccessor = httpContextAccessor;
        _context = context;
    }

    public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
    {
        if (principal.Identity is not ClaimsIdentity identity || !identity.IsAuthenticated)
        {
            return Task.FromResult(principal);
        }

        var clubsClaim = principal.FindFirst("clubs")?.Value;
        if (string.IsNullOrEmpty(clubsClaim))
        {
            return Task.FromResult(principal);
        }

        // Parse comma-separated club UUIDs
        var clubIds = clubsClaim.Split(',', StringSplitOptions.RemoveEmptyEntries)
            .Select(id => id.Trim())
            .ToArray();

        if (clubIds.Length == 0)
        {
            return Task.FromResult(principal);
        }

        var tenantId = _httpContextAccessor.HttpContext?.Request.Headers["X-Tenant-Id"].FirstOrDefault();
        if (string.IsNullOrEmpty(tenantId) || !clubIds.Contains(tenantId))
        {
            return Task.FromResult(principal);
        }

        var userIdClaim = principal.FindFirst("preferred_username")?.Value;
        if (string.IsNullOrEmpty(userIdClaim))
        {
            return Task.FromResult(principal);
        }

    // --- NEW: Skip DB role lookup if user is a global admin ---
    var realmAccess = principal.FindFirst("realm_access")?.Value;
    if (!string.IsNullOrEmpty(realmAccess) && IsAdminUser(realmAccess))
    {
      return Task.FromResult(principal);
    }
    // ---------------------------------------------------------

    static bool IsAdminUser(string realmAccess)
    {
      try
      {
        using var doc = System.Text.Json.JsonDocument.Parse(realmAccess);
        if (doc.RootElement.TryGetProperty("roles", out var rolesElement) &&
            rolesElement.ValueKind == System.Text.Json.JsonValueKind.Array)
        {
          foreach (var role in rolesElement.EnumerateArray())
          {
            if (role.GetString()?.Equals("admin", StringComparison.OrdinalIgnoreCase) == true)
              return true;
          }
        }
      }
      catch
      {
        // If JSON parsing fails, fallback to string contains check
        return realmAccess.Contains("admin", StringComparison.OrdinalIgnoreCase);
      }
      return false;
    }

        // Look up the user's role in the database for the requested tenant
        _httpContextAccessor.HttpContext!.Items["TenantId"] = tenantId;
        var memberRole = GetMemberRole(userIdClaim, tenantId);
        if (memberRole.HasValue)
        {
            var mappedRole = MapClubRoleToAspNetRole(memberRole.Value);
            identity.AddClaim(new Claim(ClaimTypes.Role, mappedRole));
        }

        return Task.FromResult(principal);
    }

    private ClubRole? GetMemberRole(string externalUserId, string tenantId)
    {
        try
        {
            var member = _context.Members
                .FirstOrDefault(m => m.Email == externalUserId && m.TenantId == tenantId);

            return member?.Role;
        }
        catch
        {
            return null;
        }
    }

    private static string MapClubRoleToAspNetRole(ClubRole clubRole)
    {
        return clubRole switch
        {

            ClubRole.Manager => "Manager",
            ClubRole.Member => "Member",
            ClubRole.Viewer => "Viewer",
            _ => "Viewer"
        };
    }
}
