using System.IdentityModel.Tokens.Jwt;
using System.Net.Http.Json;
using System.Security.Claims;

namespace ColaFlow.Modules.Identity.IntegrationTests.Infrastructure;

/// <summary>
/// Helper class for authentication-related test operations
/// Provides utilities for registration, login, token parsing, and common test scenarios
/// </summary>
public static class TestAuthHelper
{
    /// <summary>
    /// Register a new tenant and return the access token and refresh token
    /// </summary>
    public static async Task<(string accessToken, string refreshToken)> RegisterAndGetTokensAsync(
        HttpClient client,
        string? tenantSlug = null,
        string? email = null,
        string? password = null)
    {
        var slug = tenantSlug ?? $"test-{Guid.NewGuid():N}";
        var adminEmail = email ?? $"admin-{Guid.NewGuid():N}@test.com";
        var adminPassword = password ?? "Admin@1234";

        var request = new
        {
            tenantName = "Test Corp",
            tenantSlug = slug,
            subscriptionPlan = "Professional",
            adminEmail,
            adminPassword,
            adminFullName = "Test Admin"
        };

        var response = await client.PostAsJsonAsync("/api/tenants/register", request);
        response.EnsureSuccessStatusCode();

        var result = await response.Content.ReadFromJsonAsync<RegisterResponse>();

        return (result!.AccessToken, result.RefreshToken);
    }

    /// <summary>
    /// Login with credentials and return tokens
    /// </summary>
    public static async Task<(string accessToken, string refreshToken)> LoginAndGetTokensAsync(
        HttpClient client,
        string tenantSlug,
        string email,
        string password)
    {
        var request = new
        {
            tenantSlug,
            email,
            password
        };

        var response = await client.PostAsJsonAsync("/api/auth/login", request);
        response.EnsureSuccessStatusCode();

        var result = await response.Content.ReadFromJsonAsync<LoginResponse>();

        return (result!.AccessToken, result.RefreshToken);
    }

    /// <summary>
    /// Parse JWT token and extract claims
    /// </summary>
    public static IEnumerable<Claim> ParseJwtToken(string token)
    {
        var handler = new JwtSecurityTokenHandler();
        var jwtToken = handler.ReadJwtToken(token);
        return jwtToken.Claims;
    }

    /// <summary>
    /// Get specific claim value from token
    /// </summary>
    public static string? GetClaimValue(string token, string claimType)
    {
        var claims = ParseJwtToken(token);
        return claims.FirstOrDefault(c => c.Type == claimType)?.Value;
    }

    /// <summary>
    /// Verify token contains expected role
    /// </summary>
    public static bool HasRole(string token, string role)
    {
        var claims = ParseJwtToken(token);
        return claims.Any(c => c.Type == "role" && c.Value == role) ||
               claims.Any(c => c.Type == "tenant_role" && c.Value == role);
    }

    /// <summary>
    /// Extract invitation token from email HTML body
    /// </summary>
    public static string? ExtractInvitationTokenFromEmail(string htmlBody)
    {
        return ExtractTokenFromEmailBody(htmlBody, "token");
    }

    /// <summary>
    /// Extract verification token from email HTML body
    /// </summary>
    public static string? ExtractVerificationTokenFromEmail(string htmlBody)
    {
        return ExtractTokenFromEmailBody(htmlBody, "token");
    }

    /// <summary>
    /// Extract password reset token from email HTML body
    /// </summary>
    public static string? ExtractPasswordResetTokenFromEmail(string htmlBody)
    {
        return ExtractTokenFromEmailBody(htmlBody, "token");
    }

    /// <summary>
    /// Extract token from email HTML body by parameter name
    /// </summary>
    private static string? ExtractTokenFromEmailBody(string htmlBody, string tokenParam)
    {
        // Pattern to match: token=VALUE or ?token=VALUE or &token=VALUE
        var pattern = $@"[?&]{tokenParam}=([A-Za-z0-9_-]+)";
        var match = System.Text.RegularExpressions.Regex.Match(htmlBody, pattern);
        return match.Success ? match.Groups[1].Value : null;
    }
}

// Response DTOs
public record RegisterResponse(string AccessToken, string RefreshToken);
public record LoginResponse(string AccessToken, string RefreshToken);
public record RefreshResponse(string AccessToken, string RefreshToken);
public record UserInfoResponse(
    string UserId,
    string TenantId,
    string Email,
    string FullName,
    string TenantSlug,
    string TenantRole);
