using System.Collections.Concurrent;

namespace RelayServer.Services.Rtc;

public static class RtcChannelPresenceService
{
    private static readonly ConcurrentDictionary<string, string> SessionToChannel = new();
    private static readonly ConcurrentDictionary<string, string> SessionToUsername = new();

    public static void SetUser(string sessionId, string username)
    {
        SessionToUsername[sessionId] = username;
    }

    public static void JoinChannel(string sessionId, string channelId)
    {
        SessionToChannel[sessionId] = channelId;
    }

    public static void LeaveChannel(string sessionId)
    {
        SessionToChannel.TryRemove(sessionId, out _);
    }

    public static void RemoveSession(string sessionId)
    {
        SessionToChannel.TryRemove(sessionId, out _);
        SessionToUsername.TryRemove(sessionId, out _);
    }

    public static IReadOnlyList<string> GetSessionsInChannel(string channelId)
    {
        return SessionToChannel
            .Where(x => x.Value == channelId)
            .Select(x => x.Key)
            .ToList();
    }
    
    public static List<string> GetUsernamesInChannel(string channelId)
    {
        return GetUsersInChannel(channelId).ToList();
    }

    public static IReadOnlyList<string> GetUsersInChannel(string channelId)
    {
        var sessionIds = GetSessionsInChannel(channelId);

        return sessionIds
            .Where(id => SessionToUsername.ContainsKey(id))
            .Select(id => SessionToUsername[id])
            .Distinct(StringComparer.OrdinalIgnoreCase)
            .ToList();
    }

    public static bool IsInChannel(string sessionId, string channelId)
    {
        return SessionToChannel.TryGetValue(sessionId, out var currentChannel) &&
               string.Equals(currentChannel, channelId, StringComparison.Ordinal);
    }
    
    public static string? GetUsernameForSession(string sessionId)
    {
        return SessionToUsername.TryGetValue(sessionId, out var username)
            ? username
            : null;
    }
}