using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using Microsoft.Extensions.Options;
using Tiku.Application.Auth;
using Tiku.Application.Security;
using Tiku.Domain.Tenancy;

namespace Tiku.Infrastructure.Auth;

public sealed class TokenService(IOptions<JwtOptions> options, IJwtKeyRing keyRing) : ITokenService
{
    private readonly JwtOptions options = options.Value;

    public (string Token, DateTimeOffset ExpiresAt) CreateAccessToken(
        Guid userId,
        Guid sessionId,
        string? phone,
        string? email,
        AuthRealm realm,
        Guid? tenantId)
    {
        var expiresAt = DateTimeOffset.UtcNow.AddMinutes(options.AccessTokenMinutes);
        var claims = new List<Claim>
        {
            new(JwtRegisteredClaimNames.Sub, userId.ToString()),
            new(TikuClaimTypes.SessionId, sessionId.ToString()),
            new(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString("N")),
            new(JwtRegisteredClaimNames.Iat, DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString(),
                ClaimValueTypes.Integer64),
            new(TikuClaimTypes.Realm, realm.ToString().ToLowerInvariant())
        };

        if (tenantId.HasValue) claims.Add(new Claim(TikuClaimTypes.TenantId, tenantId.Value.ToString()));

        if (!string.IsNullOrWhiteSpace(phone)) claims.Add(new Claim(TikuClaimTypes.Phone, phone));

        if (!string.IsNullOrWhiteSpace(email)) claims.Add(new Claim(TikuClaimTypes.Email, email));

        var token = new JwtSecurityToken(
            options.Issuer,
            options.Audience,
            claims,
            expires: expiresAt.UtcDateTime,
            signingCredentials: keyRing.SigningCredentials);

        return (new JwtSecurityTokenHandler().WriteToken(token), expiresAt);
    }
}