using ColaFlow.Modules.Identity.Domain.Aggregates.Tenants;
using ColaFlow.Modules.Identity.Domain.Aggregates.Users;
using ColaFlow.Modules.Identity.Domain.Repositories;
using MediatR;
using Microsoft.Extensions.Logging;

namespace ColaFlow.Modules.Identity.Application.Queries.GetPendingInvitations;

public class GetPendingInvitationsQueryHandler : IRequestHandler<GetPendingInvitationsQuery, List<InvitationDto>>
{
    private readonly IInvitationRepository _invitationRepository;
    private readonly IUserRepository _userRepository;
    private readonly ILogger<GetPendingInvitationsQueryHandler> _logger;

    public GetPendingInvitationsQueryHandler(
        IInvitationRepository invitationRepository,
        IUserRepository userRepository,
        ILogger<GetPendingInvitationsQueryHandler> logger)
    {
        _invitationRepository = invitationRepository;
        _userRepository = userRepository;
        _logger = logger;
    }

    public async Task<List<InvitationDto>> Handle(GetPendingInvitationsQuery request, CancellationToken cancellationToken)
    {
        var tenantId = TenantId.Create(request.TenantId);

        // Get all pending invitations for the tenant
        var invitations = await _invitationRepository.GetPendingByTenantAsync(tenantId, cancellationToken);

        // Get all unique inviter user IDs
        var inviterIds = invitations.Select(i => (Guid)i.InvitedBy).Distinct().ToList();

        // Fetch all inviters in one query
        var inviters = await _userRepository.GetByIdsAsync(inviterIds, cancellationToken);
        var inviterDict = inviters.ToDictionary(u => u.Id, u => u.FullName.Value);

        // Map to DTOs
        var dtos = invitations.Select(i => new InvitationDto(
            Id: i.Id,
            Email: i.Email,
            Role: i.Role.ToString(),
            InvitedByName: inviterDict.TryGetValue(i.InvitedBy, out var name) ? name : "Unknown",
            InvitedById: i.InvitedBy,
            CreatedAt: i.CreatedAt,
            ExpiresAt: i.ExpiresAt
        )).ToList();

        _logger.LogInformation(
            "Retrieved {Count} pending invitations for tenant {TenantId}",
            dtos.Count,
            request.TenantId);

        return dtos;
    }
}
