package auth

import (
	"path/filepath"
	"testing"
	"time"
)

func TestSessionPersistsAcrossReopen(t *testing.T) {
	path := filepath.Join(t.TempDir(), "sessions.db")

	store, err := NewSessionStore(path)
	if err != nil {
		t.Fatal(err)
	}
	token, err := store.Create("urania")
	if err != nil {
		t.Fatal(err)
	}

	// Reopen the same file: a fresh process must still see the session.
	reopened, err := NewSessionStore(path)
	if err != nil {
		t.Fatal(err)
	}
	sess, ok := reopened.GetByToken(token)
	if !ok || sess.Username != "urania" {
		t.Fatalf("session lost after reopen: got %+v ok=%v", sess, ok)
	}
}

func TestExpiredSessionRejected(t *testing.T) {
	store, err := NewSessionStore(filepath.Join(t.TempDir(), "sessions.db"))
	if err != nil {
		t.Fatal(err)
	}
	// Create a session with an already-expired TTL (-2s ensures the Unix
	// second-rounded timestamp is safely in the past).
	oldTTL := sessionTTL
	sessionTTL = -2 * time.Second
	token, err := store.Create("urania")
	sessionTTL = oldTTL
	if err != nil {
		t.Fatal(err)
	}
	if _, ok := store.GetByToken(token); ok {
		t.Fatal("expired session was accepted")
	}
	// Lazy cleanup should have deleted the row.
	if _, ok := store.GetByToken(token); ok {
		t.Fatal("expired session still in store")
	}
}

func TestDeleteInvalidatesSession(t *testing.T) {
	store, err := NewSessionStore(filepath.Join(t.TempDir(), "sessions.db"))
	if err != nil {
		t.Fatal(err)
	}
	token, err := store.Create("urania")
	if err != nil {
		t.Fatal(err)
	}
	if _, ok := store.GetByToken(token); !ok {
		t.Fatal("session should exist before logout")
	}
	if err := store.Delete(token); err != nil {
		t.Fatal(err)
	}
	if _, ok := store.GetByToken(token); ok {
		t.Fatal("session still valid after logout")
	}
	// Deleting an unknown/already-deleted token is a no-op, not an error.
	if err := store.Delete(token); err != nil {
		t.Errorf("deleting unknown token should be a no-op, got %v", err)
	}
}

func TestUnknownTokenRejected(t *testing.T) {
	store, err := NewSessionStore(filepath.Join(t.TempDir(), "sessions.db"))
	if err != nil {
		t.Fatal(err)
	}
	if _, ok := store.GetByToken("nope"); ok {
		t.Fatal("unknown token was accepted")
	}
}
