using Insight.Web.Constants;
using Insight.Web.Models;
using System.Collections.Concurrent;
using Vaitr.MemoryBus;

namespace Insight.Web.Services;

public class SessionPool
{
    public readonly ConcurrentDictionary<string, SessionState> Sessions = new();

    private readonly IMemoryBus _bus;
    private readonly ILogger<SessionPool> _logger;

    public SessionPool(IMemoryBus bus, ILogger<SessionPool> logger)
    {
        _bus = bus;
        _logger = logger;
    }

    public async Task AddAsync(SessionState state, CancellationToken cancellationToken)
    {
        if (string.IsNullOrWhiteSpace(state.Id)) return;

        if (Sessions.TryAdd(state.Id, state) is false)
        {
            _logger.LogError($"Session ({state.Id}) add error");
            return;
        }

        _logger.LogInformation($"Session connected: {state.Id}");

        await UpdateAsync(state, cancellationToken);
    }

    public async Task RemoveAsync(SessionState state, CancellationToken cancellationToken)
    {
        if (string.IsNullOrWhiteSpace(state.Id)) return;

        if (Sessions.TryRemove(state.Id, out _) is false)
        {
            _logger.LogError($"Session ({state.Id}) remove error");
            return;
        }

        _logger.LogInformation($"Session disconnected: {state.Id}");

        await UpdateAsync(state, cancellationToken);
    }

    public async Task UpdateAsync(SessionState state, CancellationToken cancellationToken)
    {
        if (string.IsNullOrWhiteSpace(state.Id) || Sessions.ContainsKey(state.Id) is false) return;

        await _bus.PublishAsync(Events.Sessions.Changed, cancellationToken);
    }

    public bool TryGetUserSessions(string username, out IEnumerable<SessionState>? sessions)
    {
        if (Sessions.Values.Any(p => p.Username == username) is false)
        {
            sessions = null;
            return false;
        }

        sessions = Sessions.Values.Where(p => p.Username == username);
        return true;
    }
}