using Application.Abstractions.Cache;
using Application.Abstractions.Chat;
using Application.Abstractions.Hub;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging;
using StackExchange.Redis;
namespace Infrastructure.Hubs;
///
/// 공통 Hub — 모든 페이지에서 사용
/// 접속자 추적 + 채팅 + 알림 + 쪽지 + 크루 초대/동의/toast + YouTube 채팅 통합
///
public sealed class AppHub(
IConnectionMultiplexer redis,
ILogger logger
) : Hub
{
// ── 연결 관리 ────────────────────────────────────────────────
public override async Task OnConnectedAsync()
{
var memberID = GetMemberID();
if (memberID > 0)
{
var db = redis.GetDatabase();
await db.HashSetAsync(CacheKeys.ChatConnections, Context.ConnectionId, memberID);
// 개인 그룹 (알림/쪽지용)
await Groups.AddToGroupAsync(Context.ConnectionId, $"member:{memberID}");
}
await base.OnConnectedAsync();
}
public override async Task OnDisconnectedAsync(Exception? exception)
{
var db = redis.GetDatabase();
await db.HashDeleteAsync(CacheKeys.ChatConnections, Context.ConnectionId);
await base.OnDisconnectedAsync(exception);
}
// ── 채팅 그룹 참가/퇴장 ──────────────────────────────────────
public async Task JoinChat(string room)
{
await Groups.AddToGroupAsync(Context.ConnectionId, $"chat:{room}");
}
public async Task LeaveChat(string room)
{
await Groups.RemoveFromGroupAsync(Context.ConnectionId, $"chat:{room}");
}
// ── 채팅 메시지 전송 ─────────────────────────────────────────
public async Task SendMessage(string room, ChatMessage message)
{
await Clients.Group($"chat:{room}").ReceiveMessage(message);
}
// ── 채널 그룹 (크루 초대/동의 실시간 등) ─────────────────────
public async Task JoinChannel(string channelSID)
{
await Groups.AddToGroupAsync(Context.ConnectionId, $"channel:{channelSID}");
}
public async Task LeaveChannel(string channelSID)
{
await Groups.RemoveFromGroupAsync(Context.ConnectionId, $"channel:{channelSID}");
}
// ── Private ──────────────────────────────────────────────────
private int GetMemberID()
{
var claim = Context.User?.FindFirst("memberID")?.Value;
return int.TryParse(claim, out var id) ? id : 0;
}
}