package token

import (
	"fmt"
	"testing"
	"time"
)

func TestSessionStorePrunesExpiredAndCapsLiveSessions(t *testing.T) {
	sessionMu.Lock()
	previous := sessionKeys
	sessionKeys = make(map[string]sessionRecord)
	sessionKeys["expired"] = sessionRecord{
		CreatedAt: time.Now().Add(-sessionMaxDuration - time.Minute),
		ExpiresAt: time.Now().Add(-time.Minute),
	}
	sessionMu.Unlock()
	t.Cleanup(func() {
		sessionMu.Lock()
		sessionKeys = previous
		sessionMu.Unlock()
	})

	for i := 0; i < maxSessionKeys+5; i++ {
		SetSession(fmt.Sprintf("session-%03d", i))
	}

	sessionMu.RLock()
	defer sessionMu.RUnlock()
	if _, ok := sessionKeys["expired"]; ok {
		t.Fatal("expired session should be pruned")
	}
	if len(sessionKeys) > maxSessionKeys {
		t.Fatalf("sessionKeys len = %d, want <= %d", len(sessionKeys), maxSessionKeys)
	}
}

func TestSessionExpiresAtReturnsValidatedExpiry(t *testing.T) {
	sessionMu.Lock()
	previous := sessionKeys
	sessionKeys = make(map[string]sessionRecord)
	created := time.Now().Add(-time.Minute)
	sessionKeys["live"] = sessionRecord{
		CreatedAt: created,
		ExpiresAt: created.Add(sessionMaxDuration),
	}
	sessionKeys["expired"] = sessionRecord{
		CreatedAt: time.Now().Add(-sessionMaxDuration - time.Minute),
		ExpiresAt: time.Now().Add(-time.Minute),
	}
	sessionMu.Unlock()
	t.Cleanup(func() {
		sessionMu.Lock()
		sessionKeys = previous
		sessionMu.Unlock()
	})

	expiresAt, ok := SessionExpiresAt("live")
	if !ok {
		t.Fatal("live session should validate")
	}
	if !expiresAt.Equal(created.Add(sessionMaxDuration)) {
		t.Fatalf("expiresAt = %v, want %v", expiresAt, created.Add(sessionMaxDuration))
	}

	if _, ok := SessionExpiresAt("expired"); ok {
		t.Fatal("expired session should not validate")
	}
	sessionMu.RLock()
	_, retained := sessionKeys["expired"]
	sessionMu.RUnlock()
	if retained {
		t.Fatal("expired session should be removed")
	}
}
