using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace DramaLing.Api.Services;

public interface IAuthService
{
    Task<Guid?> GetUserIdFromTokenAsync(string? authorizationHeader);
    Task<ClaimsPrincipal?> ValidateTokenAsync(string token);
}

public class AuthService : IAuthService
{
    private readonly IConfiguration _configuration;
    private readonly ILogger<AuthService> _logger;

    public AuthService(IConfiguration configuration, ILogger<AuthService> logger)
    {
        _configuration = configuration;
        _logger = logger;
    }

    public async Task<Guid?> GetUserIdFromTokenAsync(string? authorizationHeader)
    {
        try
        {
            if (string.IsNullOrEmpty(authorizationHeader))
                return null;

            if (!authorizationHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
                return null;

            var token = authorizationHeader["Bearer ".Length..].Trim();
            var claimsPrincipal = await ValidateTokenAsync(token);

            if (claimsPrincipal == null)
                return null;

            var userIdString = claimsPrincipal.FindFirst(ClaimTypes.NameIdentifier)?.Value ??
                             claimsPrincipal.FindFirst("sub")?.Value;

            if (Guid.TryParse(userIdString, out var userId))
                return userId;

            return null;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error extracting user ID from token");
            return null;
        }
    }

    public async Task<ClaimsPrincipal?> ValidateTokenAsync(string token)
    {
        try
        {
            // 優先從環境變數讀取，再從配置讀取
            var jwtSecret = Environment.GetEnvironmentVariable("DRAMALING_SUPABASE_JWT_SECRET")
                ?? _configuration["Supabase:JwtSecret"];

            if (string.IsNullOrEmpty(jwtSecret))
            {
                _logger.LogError("Supabase JWT Secret not configured in environment variables or config");
                return null;
            }

            var tokenHandler = new JwtSecurityTokenHandler();
            var key = Encoding.UTF8.GetBytes(jwtSecret);

            var validationParameters = new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateLifetime = true,
                ValidateIssuerSigningKey = true,
                ValidIssuer = Environment.GetEnvironmentVariable("DRAMALING_SUPABASE_URL")
                    ?? _configuration["Supabase:Url"]
                    ?? "https://localhost",
                ValidAudience = "authenticated",
                IssuerSigningKey = new SymmetricSecurityKey(key),
                ClockSkew = TimeSpan.FromMinutes(5) // 允許 5 分鐘時間偏差
            };

            var principal = tokenHandler.ValidateToken(token, validationParameters, out _);
            return principal;
        }
        catch (SecurityTokenException ex)
        {
            _logger.LogWarning("Invalid JWT token: {Message}", ex.Message);
            return null;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error validating JWT token");
            return null;
        }
    }
}