using ColaFlow.Modules.Identity.Domain.Aggregates.Invitations;
using ColaFlow.Modules.Identity.Domain.Aggregates.Tenants;
using ColaFlow.Modules.Identity.Domain.Repositories;
using Microsoft.EntityFrameworkCore;

namespace ColaFlow.Modules.Identity.Infrastructure.Persistence.Repositories;

public class InvitationRepository(IdentityDbContext context) : IInvitationRepository
{
    public async Task<Invitation?> GetByIdAsync(InvitationId id, CancellationToken cancellationToken = default)
    {
        return await context.Invitations
            .FirstOrDefaultAsync(i => i.Id == id, cancellationToken);
    }

    public async Task<Invitation?> GetByTokenHashAsync(string tokenHash, CancellationToken cancellationToken = default)
    {
        return await context.Invitations
            .FirstOrDefaultAsync(i => i.TokenHash == tokenHash, cancellationToken);
    }

    public async Task<List<Invitation>> GetPendingByTenantAsync(TenantId tenantId, CancellationToken cancellationToken = default)
    {
        var now = DateTime.UtcNow;
        return await context.Invitations
            .Where(i => i.TenantId == tenantId &&
                       i.AcceptedAt == null &&
                       i.ExpiresAt > now)
            .OrderByDescending(i => i.CreatedAt)
            .ToListAsync(cancellationToken);
    }

    public async Task<Invitation?> GetPendingByEmailAndTenantAsync(
        string email,
        TenantId tenantId,
        CancellationToken cancellationToken = default)
    {
        var now = DateTime.UtcNow;
        var normalizedEmail = email.ToLowerInvariant();

        return await context.Invitations
            .FirstOrDefaultAsync(i =>
                i.TenantId == tenantId &&
                i.Email == normalizedEmail &&
                i.AcceptedAt == null &&
                i.ExpiresAt > now,
                cancellationToken);
    }

    public async Task AddAsync(Invitation invitation, CancellationToken cancellationToken = default)
    {
        await context.Invitations.AddAsync(invitation, cancellationToken);
        await context.SaveChangesAsync(cancellationToken);
    }

    public async Task UpdateAsync(Invitation invitation, CancellationToken cancellationToken = default)
    {
        context.Invitations.Update(invitation);
        await context.SaveChangesAsync(cancellationToken);
    }

    public async Task DeleteAsync(Invitation invitation, CancellationToken cancellationToken = default)
    {
        context.Invitations.Remove(invitation);
        await context.SaveChangesAsync(cancellationToken);
    }
}
