using MediatR;
using ChatService.Domain.AggregatesModel.ConversationAggregate;
using ChatService.Domain.AggregatesModel.UserAggregate;

namespace ChatService.API.Application.Queries.Conversations;

/// <summary>
/// EN: Handler for GetConversationsQuery.
/// VI: Handler cho GetConversationsQuery.
/// </summary>
public class GetConversationsQueryHandler : IRequestHandler<GetConversationsQuery, GetConversationsResult>
{
    private readonly IConversationRepository _conversationRepository;
    private readonly IChatUserRepository _chatUserRepository;
    private readonly ILogger<GetConversationsQueryHandler> _logger;

    public GetConversationsQueryHandler(
        IConversationRepository conversationRepository,
        IChatUserRepository chatUserRepository,
        ILogger<GetConversationsQueryHandler> logger)
    {
        _conversationRepository = conversationRepository;
        _chatUserRepository = chatUserRepository;
        _logger = logger;
    }

    public async Task<GetConversationsResult> Handle(GetConversationsQuery request, CancellationToken cancellationToken)
    {
        _logger.LogInformation("Getting conversations for user {UserId}, page {Page}", request.UserId, request.Page);

        var (conversations, totalCount) = await _conversationRepository.GetConversationsForUserAsync(
            request.UserId, request.Page, request.PageSize, cancellationToken);

        var conversationList = conversations.ToList();
        var conversationDtos = new List<ConversationDto>();

        foreach (var conversation in conversationList)
        {
            // EN: Get participant user info
            // VI: Lấy thông tin user của participants
            var participantIds = conversation.Participants.Select(p => p.UserId).ToList();
            var users = await _chatUserRepository.GetByIdsAsync(participantIds, cancellationToken);
            var userDict = users.ToDictionary(u => u.Id);

            var participantDtos = conversation.Participants.Select(p => new ConversationParticipantDto(
                p.UserId,
                userDict.TryGetValue(p.UserId, out var user) ? user.DisplayName : "Unknown",
                userDict.TryGetValue(p.UserId, out var u) ? u.AvatarUrl : null,
                p.IsAdmin ? "admin" : "member",
                p.LastReadAt
            )).ToList();

            // EN: Get unread count
            // VI: Lấy số tin chưa đọc
            var unreadCount = await _conversationRepository.GetUnreadMessageCountAsync(
                conversation.Id, request.UserId, cancellationToken);

            // EN: Get last message info
            // VI: Lấy thông tin tin nhắn cuối
            LastMessageDto? lastMessage = null;

            if (conversation.LastMessageId.HasValue)
            {
                var messages = await _conversationRepository.GetMessagesAsync(
                    conversation.Id, 0, 1, null, cancellationToken);
                var lastMsg = messages.FirstOrDefault();
                if (lastMsg != null)
                {
                    var senderName = userDict.TryGetValue(lastMsg.SenderId, out var sender) 
                        ? sender.DisplayName 
                        : "Unknown";
                    lastMessage = new LastMessageDto(
                        lastMsg.Id,
                        lastMsg.SenderId,
                        senderName,
                        lastMsg.Type.Name,
                        lastMsg.CreatedAt
                    );
                }
            }

            conversationDtos.Add(new ConversationDto(
                conversation.Id,
                conversation.Type.Name,
                conversation.Name,
                conversation.AvatarUrl,
                participantDtos,
                lastMessage,
                unreadCount,
                conversation.CreatedAt,
                conversation.UpdatedAt
            ));
        }

        return new GetConversationsResult(
            conversationDtos,
            totalCount,
            request.Page,
            request.PageSize
        );
    }
}
