using ColaFlow.Modules.ProjectManagement.Domain.Repositories;
using ColaFlow.Shared.Kernel.Common;

namespace ColaFlow.Modules.ProjectManagement.Infrastructure.Persistence;

/// <summary>
/// Unit of Work implementation for ProjectManagement module
/// </summary>
public class UnitOfWork(PMDbContext context) : IUnitOfWork
{
    private readonly PMDbContext _context = context ?? throw new ArgumentNullException(nameof(context));

    public async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
    {
        // Dispatch domain events before saving
        await DispatchDomainEventsAsync(cancellationToken);

        // Save changes to database
        return await _context.SaveChangesAsync(cancellationToken);
    }

    private async Task DispatchDomainEventsAsync(CancellationToken cancellationToken)
    {
        // Get all entities with domain events
        var domainEntities = _context.ChangeTracker
            .Entries<AggregateRoot>()
            .Where(x => x.Entity.DomainEvents.Any())
            .Select(x => x.Entity)
            .ToList();

        // Get all domain events
        var domainEvents = domainEntities
            .SelectMany(x => x.DomainEvents)
            .ToList();

        // Clear domain events from entities
        domainEntities.ForEach(entity => entity.ClearDomainEvents());

        // TODO: Dispatch domain events to handlers
        // This will be implemented when we add MediatR
        // For now, we just clear the events
        await Task.CompletedTask;
    }
}
