using System.Text.RegularExpressions;
using ASTRAIN.Api.Data;
using ASTRAIN.Shared.Models;
using Microsoft.EntityFrameworkCore;

namespace ASTRAIN.Api.Services;

/// <summary>
/// Provides helper methods for ensuring and validating application users.
/// </summary>
internal static class UserProvisioning
{
    /// <summary>
    /// Ensures a user exists in the database and returns the user record.
    /// </summary>
    /// <param name="db">The application database context.</param>
    /// <param name="userId">Optional user id to validate or create.</param>
    /// <returns>The existing or newly created user.</returns>
    public static async Task<User> EnsureUserAsync(AppDbContext db, string? userId)
    {
        if (!string.IsNullOrWhiteSpace(userId) && IsValidUserId(userId))
        {
            var existing = await db.Users.FirstOrDefaultAsync(u => u.Id == userId);
            if (existing is not null)
            {
                return existing;
            }

            var created = new User { Id = userId };
            db.Users.Add(created);
            await db.SaveChangesAsync();
            return created;
        }

        while (true)
        {
            var newId = UserKeyGenerator.Generate(8);
            var exists = await db.Users.AnyAsync(u => u.Id == newId);
            if (exists)
            {
                continue;
            }

            var user = new User { Id = newId };
            db.Users.Add(user);
            await db.SaveChangesAsync();
            return user;
        }
    }

    /// <summary>
    /// Determines whether a user id matches the expected format.
    /// </summary>
    /// <param name="userId">The user id to validate.</param>
    /// <returns><c>true</c> if the id is valid; otherwise <c>false</c>.</returns>
    public static bool IsValidUserId(string userId)
    {
        return Regex.IsMatch(userId, "^[A-Za-z0-9]{8}$");
    }
}
