using Microsoft.EntityFrameworkCore;
using IamService.Domain.AggregatesModel.PrivilegedAccessAggregate;
using IamService.Domain.SeedWork;

namespace IamService.Infrastructure.Repositories;

/// <summary>
/// EN: Repository implementation for PrivilegedAccessGrant aggregate.
/// VI: Repository implementation cho PrivilegedAccessGrant aggregate.
/// </summary>
public class PrivilegedAccessRepository : IPrivilegedAccessRepository
{
    private readonly IamServiceContext _context;
    public IUnitOfWork UnitOfWork => _context;

    public PrivilegedAccessRepository(IamServiceContext context) => _context = context;

    public PrivilegedAccessGrant Add(PrivilegedAccessGrant grant) => _context.PrivilegedAccessGrants.Add(grant).Entity;

    public void Update(PrivilegedAccessGrant grant) => _context.Entry(grant).State = EntityState.Modified;

    public async Task<PrivilegedAccessGrant?> GetByIdAsync(Guid id, CancellationToken cancellationToken = default)
        => await _context.PrivilegedAccessGrants.FirstOrDefaultAsync(x => x.Id == id, cancellationToken);

    public async Task<IEnumerable<PrivilegedAccessGrant>> GetActiveByUserIdAsync(Guid userId, CancellationToken cancellationToken = default)
    {
        var now = DateTime.UtcNow;
        return await _context.PrivilegedAccessGrants
            .Where(x => EF.Property<Guid>(x, "_userId") == userId)
            .Where(x => EF.Property<PrivilegedAccessStatus>(x, "_status") == PrivilegedAccessStatus.Active)
            .Where(x => EF.Property<DateTime>(x, "_startsAt") <= now)
            .Where(x => EF.Property<DateTime>(x, "_expiresAt") > now)
            .ToListAsync(cancellationToken);
    }

    public async Task<IEnumerable<PrivilegedAccessGrant>> GetExpiredGrantsAsync(CancellationToken cancellationToken = default)
    {
        var now = DateTime.UtcNow;
        return await _context.PrivilegedAccessGrants
            .Where(x => EF.Property<PrivilegedAccessStatus>(x, "_status") == PrivilegedAccessStatus.Active)
            .Where(x => EF.Property<DateTime>(x, "_expiresAt") <= now)
            .ToListAsync(cancellationToken);
    }

    public async Task<bool> HasActiveGrantAsync(Guid userId, Guid roleId, CancellationToken cancellationToken = default)
    {
        var now = DateTime.UtcNow;
        return await _context.PrivilegedAccessGrants
            .AnyAsync(x => 
                EF.Property<Guid>(x, "_userId") == userId &&
                EF.Property<Guid>(x, "_roleId") == roleId &&
                EF.Property<PrivilegedAccessStatus>(x, "_status") == PrivilegedAccessStatus.Active &&
                EF.Property<DateTime>(x, "_startsAt") <= now &&
                EF.Property<DateTime>(x, "_expiresAt") > now, 
                cancellationToken);
    }
}
