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;

/// <summary>
/// 공통 Hub — 모든 페이지에서 사용
/// 접속자 추적 + 채팅 + 알림 + 쪽지 + 크루 초대/동의/toast + YouTube 채팅 통합
/// </summary>
public sealed class AppHub(
    IConnectionMultiplexer redis,
    ILogger<AppHub> logger
) : Hub<IAppHubClient>
{
    // ── 연결 관리 ────────────────────────────────────────────────

    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;
    }
}