package user_test

import (
	"context"
	"database/sql"
	"testing"
	"time"

	"galaxy/backend/internal/user"

	"github.com/google/uuid"
)

func TestCacheGetReturnsFalseUntilAdded(t *testing.T) {
	t.Parallel()
	cache := user.NewCache()
	if _, ok := cache.Get(uuid.New()); ok {
		t.Fatalf("Get on empty cache returned ok=true")
	}
}

func TestCacheReadyFlipsAfterWarm(t *testing.T) {
	t.Parallel()
	cache := user.NewCache()
	if cache.Ready() {
		t.Fatalf("Ready() = true before Warm")
	}
	store := user.NewStore(stubDB(t))
	if err := cache.Warm(context.Background(), store); err == nil {
		t.Fatalf("Warm against an empty stub DB unexpectedly succeeded")
	}
	if cache.Ready() {
		t.Fatalf("Ready() flipped after a failed Warm")
	}
}

func TestCacheAddIsVisibleToReader(t *testing.T) {
	t.Parallel()
	cache := user.NewCache()
	id := uuid.New()
	now := time.Date(2026, 5, 3, 12, 0, 0, 0, time.UTC)
	cache.Add(user.EntitlementSnapshot{
		UserID:                 id,
		Tier:                   user.TierFree,
		IsPaid:                 false,
		Source:                 "system",
		Actor:                  user.ActorRef{Type: "system"},
		StartsAt:               now,
		MaxRegisteredRaceNames: 1,
		UpdatedAt:              now,
	})
	got, ok := cache.Get(id)
	if !ok {
		t.Fatalf("Get after Add returned ok=false")
	}
	if got.Tier != user.TierFree {
		t.Fatalf("Get returned tier %q, want %q", got.Tier, user.TierFree)
	}
	if cache.Size() != 1 {
		t.Fatalf("Size = %d, want 1", cache.Size())
	}
}

// stubDB returns a *sql.DB that fails every query. Used only by the
// "Warm-on-failure does not flip Ready" test where the actual driver
// behaviour is irrelevant.
func stubDB(t *testing.T) *sql.DB {
	t.Helper()
	// sql.Open("postgres", ...) without a registered driver returns
	// an error; use a malformed DSN against the stdlib's bundled
	// `unknown` driver to force a query-time failure. We rely on
	// pgx-stdlib being already registered by the project, so the
	// driver name "pgx" is safe to use even when the DSN is bogus.
	db, err := sql.Open("pgx", "postgres://disabled.invalid:5432/none?sslmode=disable&connect_timeout=1")
	if err != nil {
		t.Fatalf("sql.Open: %v", err)
	}
	t.Cleanup(func() { _ = db.Close() })
	return db
}
