using ColaFlow.Modules.Identity.Domain.Aggregates.Users;
using ColaFlow.Modules.Identity.Domain.Entities;
using ColaFlow.Modules.Identity.Domain.Repositories;
using Microsoft.EntityFrameworkCore;

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

public class PasswordResetTokenRepository(IdentityDbContext context) : IPasswordResetTokenRepository
{
    public async Task<PasswordResetToken?> GetByTokenHashAsync(
        string tokenHash,
        CancellationToken cancellationToken = default)
    {
        return await context.PasswordResetTokens
            .FirstOrDefaultAsync(t => t.TokenHash == tokenHash, cancellationToken);
    }

    public async Task AddAsync(
        PasswordResetToken token,
        CancellationToken cancellationToken = default)
    {
        await context.PasswordResetTokens.AddAsync(token, cancellationToken);
        await context.SaveChangesAsync(cancellationToken);
    }

    public async Task UpdateAsync(
        PasswordResetToken token,
        CancellationToken cancellationToken = default)
    {
        context.PasswordResetTokens.Update(token);
        await context.SaveChangesAsync(cancellationToken);
    }

    public async Task InvalidateAllForUserAsync(
        UserId userId,
        CancellationToken cancellationToken = default)
    {
        // Mark all active (unused and non-expired) tokens as expired
        var activeTokens = await context.PasswordResetTokens
            .Where(t => t.UserId == userId && t.UsedAt == null && t.ExpiresAt > DateTime.UtcNow)
            .ToListAsync(cancellationToken);

        foreach (var token in activeTokens)
        {
            // Force expire by setting expiration to past
            context.Entry(token).Property("ExpiresAt").CurrentValue = DateTime.UtcNow.AddMinutes(-1);
        }

        if (activeTokens.Count > 0)
        {
            await context.SaveChangesAsync(cancellationToken);
        }
    }
}
