using Knot.Shared.Kernel;
using Knot.Contracts.Conversations.Domain;
using Knot.Modules.Conversations.Infrastructure.SignalR;
using MediatR;
using Microsoft.AspNetCore.SignalR;

namespace Knot.Modules.Conversations.Infrastructure.Handlers;

/// <summary>
/// Обработчик доменного события создания чата.
/// </summary>
public sealed class ChatCreatedDomainEventHandler : INotificationHandler<ChatCreatedDomainEvent>, INotificationHandler<ChatMemberAddedDomainEvent>
{
    private readonly IHubContext<ChatHub> _hubContext;
    private readonly IChatRepository _chatRepository;
    private readonly IUserDisplayNameProvider _displayNameProvider;

    public ChatCreatedDomainEventHandler(
        IHubContext<ChatHub> hubContext,
        IChatRepository chatRepository,
        IUserDisplayNameProvider displayNameProvider)
    {
        _hubContext = hubContext;
        _chatRepository = chatRepository;
        _displayNameProvider = displayNameProvider;
    }

    public async Task Handle(ChatCreatedDomainEvent notification, CancellationToken cancellationToken)
    {
        await NotifyNewChatAsync(notification.Chat, cancellationToken);
    }

    public async Task Handle(ChatMemberAddedDomainEvent notification, CancellationToken cancellationToken)
    {
        var chat = await _chatRepository.GetByIdAsync(notification.ChatId, cancellationToken);
        if (chat != null)
        {
            // Уведомляем всех участников, что кто-то добавлен (или пользователь сам видит новый чат)
            await NotifyNewChatAsync(chat, cancellationToken);
        }
    }

    private async Task NotifyNewChatAsync(Chat chat, CancellationToken cancellationToken, string? targetUserId = null)
    {
        var members = new List<object>();
        foreach (var member in chat.Members)
        {
            var userInfo = await _displayNameProvider.GetUserInfoAsync(member.UserId, cancellationToken);
            members.Add(new
            {
                member.Id,
                member.UserId,
                member.Role,
                member.JoinedAt,
                User = userInfo != null
                    ? new { userInfo.Id, userInfo.Username, userInfo.DisplayName, userInfo.Avatar, isOnline = false }
                    : new { Id = member.UserId, Username = "unknown", DisplayName = "Unknown", Avatar = (string?)null, isOnline = false }
            });
        }

        var payload = new
        {
            id = chat.Id,
            type = chat.Type.ToString().ToLowerInvariant(),
            name = chat.Type == ChatType.Favorites ? "Избранное" : (chat.Type == ChatType.Personal ? null : chat.Name),
            avatar = chat.Avatar,
            createdAt = chat.CreatedAt,
            members = members,
            messages = new List<object>(),
            unreadCount = 0
        };

        if (targetUserId != null)
        {
            // Отправляем конкретному пользователю (по всем его соединениям)
            // Мы можем использовать метод Hub или просто отправить в группу UserId (если она есть)
            // В нашем ChatHub мы добавляем пользователя в группы чатов при подключении.
            // Но для нового чата он еще не в группе. 
            // Поэтому отправляем через User ID (SignalR поддерживает Clients.User(id))
            await _hubContext.Clients.User(targetUserId).SendAsync("new_chat", payload, cancellationToken);
        }
        else
        {
            // Уведомляем всех текущих участников
            foreach (var member in chat.Members)
            {
                await _hubContext.Clients.User(member.UserId.ToString()).SendAsync("new_chat", payload, cancellationToken);
            }
        }
    }
}

