using System;
using System.Text;
using FluentAssertions;
using NexusReader.UI.Shared.Services;
using Xunit;

namespace NexusReader.Application.Tests.Services;

public class JwtTokenValidatorTests
{
    private string CreateMockToken(long exp)
    {
        // {"alg":"HS256","typ":"JWT"}
        var header = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"; 
        
        var payloadJson = $"{{\"exp\":{exp}}}";
        var payloadBytes = Encoding.UTF8.GetBytes(payloadJson);
        var payload = Convert.ToBase64String(payloadBytes)
            .Replace('+', '-')
            .Replace('/', '_')
            .TrimEnd('=');
            
        return $"{header}.{payload}.signature";
    }

    [Fact]
    public void IsExpired_WithNullOrEmptyToken_ShouldReturnTrue()
    {
        JwtTokenValidator.IsExpired(null).Should().BeTrue();
        JwtTokenValidator.IsExpired("").Should().BeTrue();
        JwtTokenValidator.IsExpired("   ").Should().BeTrue();
    }

    [Fact]
    public void IsExpired_WithMalformedToken_ShouldReturnTrue()
    {
        JwtTokenValidator.IsExpired("not.a.valid.token.format.here").Should().BeTrue();
        JwtTokenValidator.IsExpired("part1.part2").Should().BeTrue();
        JwtTokenValidator.IsExpired("justonestring").Should().BeTrue();
    }

    [Fact]
    public void IsExpired_WithExpiredToken_ShouldReturnTrue()
    {
        // Expired 1 hour ago
        var expiredTime = DateTimeOffset.UtcNow.AddHours(-1).ToUnixTimeSeconds();
        var token = CreateMockToken(expiredTime);

        JwtTokenValidator.IsExpired(token).Should().BeTrue();
    }

    [Fact]
    public void IsExpired_WithValidToken_ShouldReturnFalse()
    {
        // Valid for 1 hour in the future
        var futureTime = DateTimeOffset.UtcNow.AddHours(1).ToUnixTimeSeconds();
        var token = CreateMockToken(futureTime);

        JwtTokenValidator.IsExpired(token).Should().BeFalse();
    }

    [Fact]
    public void IsExpired_WithTokenInsideSkewBuffer_ShouldReturnTrue()
    {
        // Expiring in 5 seconds (within the 10-second skew buffer)
        var skewTime = DateTimeOffset.UtcNow.AddSeconds(5).ToUnixTimeSeconds();
        var token = CreateMockToken(skewTime);

        JwtTokenValidator.IsExpired(token).Should().BeTrue();
    }
}
