using Microsoft.EntityFrameworkCore;
using Modules.User.Application.Repositories;
using Modules.User.Database.Database;

namespace Modules.User.Database.Queries;

public sealed class AccountAccessQueries(UserDbContext context) : IAccountAccessQueries
{
    private IQueryable<Database.Entities.Account> GetAccountQuery(Guid accountId)
    {
        return context.Accounts
            .Where(q => q.Id == accountId)
            .AsNoTracking();
    }

    public async Task<IReadOnlyList<string>> GetRoleNamesAsync(Guid accountId, CancellationToken cancellationToken = default)
    {
        return await GetAccountQuery(accountId)
            // .Include(q => q.Roles).ThenInclude(q => q.Role)
            .SelectMany(q => q.Roles)
            .Where(q => !q.RevokedAtUtc.HasValue && !q.Role.Deleted)
            .Select(q => q.Role.Name)
            .ToListAsync(cancellationToken);
    }

    public async Task<IReadOnlyList<string>> GetPermissionNamesAsync(Guid accountId, CancellationToken cancellationToken = default)
    {
        return await GetAccountQuery(accountId)
            // .Include(q => q.Permissions).ThenInclude(q => q.Permission)
            .SelectMany(q => q.Permissions)
            .Where(q => !q.RevokedAtUtc.HasValue && !q.Permission.Deleted)
            .Select(q => q.Permission.Name)
            .ToListAsync(cancellationToken);
    }

    public async Task<IReadOnlyList<string>> GetEffectivePermissionCodesAsync(Guid accountId, CancellationToken cancellationToken = default)
    {
        var permissions = GetAccountQuery(accountId)
            // .Include(q => q.Permissions).ThenInclude(q => q.Permission)
            .SelectMany(q => q.Permissions)
            .Where(q => !q.RevokedAtUtc.HasValue && !q.Permission.Deleted)
            .Select(q => q.Permission.Code);
        
        var rolePermissions = GetAccountQuery(accountId)
            // .Include(q => q.Roles)
            //     .ThenInclude(q => q.Role)
            //     .ThenInclude(q => q.Permissions)
            .SelectMany(q => q.Roles)
            .Where(q => !q.RevokedAtUtc.HasValue && !q.Role.Deleted)
                .SelectMany(q => q.Role.Permissions)
                .Where(q => !q.Deleted)
                    .Select(q => q.Code);
        return await permissions.Union(rolePermissions)
            .Distinct()
            .ToListAsync(cancellationToken);
    }
}
