using System.Collections;
using System.Collections.Concurrent;
using Femto.Modules.Auth.Models;
using Microsoft.Extensions.Caching.Memory;

namespace Femto.Modules.Auth.Infrastructure;

internal class SessionStorage(TimeProvider timeProvider)
{
    private readonly IMemoryCache _storage = new MemoryCache(new MemoryCacheOptions());

    public async Task<Session?> GetSession(string id)
    {
        var session = this._storage.Get<Session>($"session:{id}");

        if (session is null)
            return null;

        var invalidUntil = this._storage.Get<DateTimeOffset?>(
            $"user:invalid_until:{session.UserId}"
        );

        if (invalidUntil is not null && invalidUntil > session.Expires)
            return null;

        return session;
    }

    public Task AddSession(Session session)
    {
        using var sessionEntry = this._storage.CreateEntry($"session:{session.Id}");
        sessionEntry.Value = session;
        sessionEntry.SetAbsoluteExpiration(session.Expires);

        return Task.CompletedTask;
    }

    public Task DeleteSession(string id)
    {
        this._storage.Remove($"session:{id}");

        return Task.CompletedTask;
    }

    public Task InvalidateUserSessions(Guid userId)
    {
        var invalidUntil = timeProvider.GetUtcNow() + Session.ValidityPeriod;

        // invalidate sessions who are currently valid
        // any sessions created after this will have a validity period that extends past invalid_until
        // this cache entry doesn't need to live longer than that point in time
        this._storage.Set($"user:invalid_until:{userId}", invalidUntil, invalidUntil);

        return Task.CompletedTask;
    }
}
