using System.Security.Cryptography;
using System.Text;

namespace SIGCM2.Application.Common;

/// <summary>
/// Generates cryptographically secure temporary passwords.
/// Excludes visually ambiguous characters (I, O, l, o, 0, 1).
/// </summary>
public static class TempPasswordGenerator
{
    private const string UpperChars = "ABCDEFGHJKLMNPQRSTUVWXYZ"; // no I, O
    private const string LowerChars = "abcdefghijkmnpqrstuvwxyz"; // no l, o
    private const string DigitChars = "23456789";                  // no 0, 1
    private const string SymbolChars = "!@#$%&*+-=?";             // copy-paste safe

    private const string Charset = UpperChars + LowerChars + DigitChars + SymbolChars;

    public static string Generate(int length = 12)
    {
        if (length < 8)
            throw new ArgumentOutOfRangeException(nameof(length), "Password length must be at least 8.");

        // SECURITY: NEVER log the result of this method
        Span<byte> bytes = stackalloc byte[length];
        RandomNumberGenerator.Fill(bytes);

        var sb = new StringBuilder(length);
        for (int i = 0; i < length; i++)
            sb.Append(Charset[bytes[i] % Charset.Length]);

        var result = sb.ToString();

        // Guarantee diversity: at least 1 upper, 1 lower, 1 digit, 1 symbol
        return HasDiversity(result) ? result : Generate(length);
    }

    private static bool HasDiversity(string pwd)
        => pwd.Any(c => UpperChars.Contains(c))
        && pwd.Any(c => LowerChars.Contains(c))
        && pwd.Any(c => DigitChars.Contains(c))
        && pwd.Any(c => SymbolChars.Contains(c));
}
