using System.Security.Cryptography;
using System.Text;
using Microsoft.Extensions.Options;
using OmsorgCore.Application.Abstractions;

namespace OmsorgCore.Infrastructure.Security;

public class PasswordResetCodeGenerator : IPasswordResetCodeGenerator
{
    private readonly PasswordResetOptions _options;

    public PasswordResetCodeGenerator(IOptions<PasswordResetOptions> options)
    {
        _options = options.Value;
    }

    public TimeSpan RequestCooldown => TimeSpan.FromSeconds(_options.RequestCooldownSeconds);

    public int MaxAttempts => _options.MaxAttempts;

    public (string RawPin, string PinHash, DateTime ExpiresAt) GeneratePin()
        => GeneratePin(TimeSpan.FromMinutes(_options.PinExpiryMinutes));

    public (string RawPin, string PinHash, DateTime ExpiresAt) GeneratePin(TimeSpan validity)
    {
        var rawPin = RandomNumberGenerator.GetInt32(0, 1_000_000).ToString("D6");
        var expiresAt = DateTime.UtcNow.Add(validity);
        return (rawPin, HashPin(rawPin), expiresAt);
    }

    public (string RawResetToken, string ResetTokenHash, DateTime ExpiresAt) GenerateResetToken()
    {
        var rawResetToken = Convert.ToBase64String(RandomNumberGenerator.GetBytes(64));
        var expiresAt = DateTime.UtcNow.AddMinutes(_options.ResetTokenExpiryMinutes);
        return (rawResetToken, HashResetToken(rawResetToken), expiresAt);
    }

    public string HashPin(string rawPin)
        => Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(rawPin)));

    public string HashResetToken(string rawResetToken)
        => Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(rawResetToken)));
}
