using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Options;
using System.Security.Cryptography;
using TakeoutSaaS.Application.Identity.Abstractions;
using TakeoutSaaS.Infrastructure.Identity.Options;

namespace TakeoutSaaS.Infrastructure.Identity.Services;

/// <summary>
/// Redis 管理后台重置密码链接令牌存储。
/// </summary>
public sealed class RedisAdminPasswordResetTokenStore(
    IDistributedCache cache,
    IOptions<AdminPasswordResetOptions> options)
    : IAdminPasswordResetTokenStore
{
    private readonly AdminPasswordResetOptions _options = options.Value;

    /// <inheritdoc />
    public async Task<string> IssueAsync(long userId, DateTime expiresAt, CancellationToken cancellationToken = default)
    {
        // 1. 生成 URL 安全的随机令牌
        var token = GenerateUrlSafeToken(48);

        // 2. 写入缓存（Value：userId）
        await cache.SetStringAsync(BuildKey(token), userId.ToString(), new DistributedCacheEntryOptions
        {
            AbsoluteExpiration = expiresAt
        }, cancellationToken);

        // 3. 返回令牌
        return token;
    }

    /// <inheritdoc />
    public async Task<long?> ConsumeAsync(string token, CancellationToken cancellationToken = default)
    {
        // 1. 读取缓存
        var key = BuildKey(token);
        var value = await cache.GetStringAsync(key, cancellationToken);
        if (string.IsNullOrWhiteSpace(value))
        {
            return null;
        }

        // 2. 删除缓存（一次性令牌）
        await cache.RemoveAsync(key, cancellationToken);

        // 3. 解析用户 ID
        return long.TryParse(value, out var userId) ? userId : null;
    }

    private string BuildKey(string token) => $"{_options.Prefix}{token}";

    private static string GenerateUrlSafeToken(int bytesLength)
    {
        var bytes = RandomNumberGenerator.GetBytes(bytesLength);
        var token = Convert.ToBase64String(bytes);

        return token
            .Replace('+', '-')
            .Replace('/', '_')
            .TrimEnd('=');
    }
}

