package playlists_test

import (
	"context"
	"testing"
	"time"

	"github.com/jackc/pgx/v5/pgtype"
	"github.com/jackc/pgx/v5/pgxpool"

	"git.fabledsword.com/bvandeusen/minstrel/internal/playlists"
)

// countYouMightLike returns the persisted row counts for a user.
func countYouMightLike(t *testing.T, pool *pgxpool.Pool, userID pgtype.UUID) (albums, artists int) {
	t.Helper()
	ctx := context.Background()
	if err := pool.QueryRow(ctx,
		`SELECT count(*) FROM you_might_like_albums WHERE user_id = $1`, userID,
	).Scan(&albums); err != nil {
		t.Fatalf("count albums: %v", err)
	}
	if err := pool.QueryRow(ctx,
		`SELECT count(*) FROM you_might_like_artists WHERE user_id = $1`, userID,
	).Scan(&artists); err != nil {
		t.Fatalf("count artists: %v", err)
	}
	return albums, artists
}

// TestYouMightLike_ColdStartGate: a thin profile (3 artists × 3 tracks =
// 9 distinct tracks, below the 20-track / 5-artist gate) must produce no
// You-might-like rows — the build ships nothing rather than near-random
// tiles.
func TestYouMightLike_ColdStartGate(t *testing.T) {
	pool := newPool(t)
	logger := discardLogger()
	u, _ := seedActiveLibrary(t, pool, "ymlcold", 3, 3)

	if err := playlists.BuildSystemPlaylists(
		context.Background(), pool, logger, u.ID, time.Now().UTC(), t.TempDir(),
	); err != nil {
		t.Fatalf("build: %v", err)
	}

	albums, artists := countYouMightLike(t, pool, u.ID)
	if albums != 0 || artists != 0 {
		t.Errorf("cold-start user should have no you-might-like rows; got %d albums, %d artists",
			albums, artists)
	}
}

// TestYouMightLike_SufficientActivityPopulates: a rich profile (8 artists
// × 4 tracks = 32 distinct tracks, clearing both gate bars) populates the
// You-might-like tables in the daily build.
func TestYouMightLike_SufficientActivityPopulates(t *testing.T) {
	pool := newPool(t)
	logger := discardLogger()
	u, _ := seedActiveLibrary(t, pool, "ymlrich", 8, 4)

	if err := playlists.BuildSystemPlaylists(
		context.Background(), pool, logger, u.ID, time.Now().UTC(), t.TempDir(),
	); err != nil {
		t.Fatalf("build: %v", err)
	}

	albums, artists := countYouMightLike(t, pool, u.ID)
	if albums == 0 {
		t.Error("rich user should have you-might-like album rows; got 0")
	}
	if artists == 0 {
		t.Error("rich user should have you-might-like artist rows; got 0")
	}
}

// TestYouMightLike_AtomicReplace: a second build replaces rather than
// appends, so counts stay bounded by the persisted depth.
func TestYouMightLike_AtomicReplace(t *testing.T) {
	pool := newPool(t)
	logger := discardLogger()
	u, _ := seedActiveLibrary(t, pool, "ymlreplace", 8, 4)
	ctx := context.Background()

	for i := 0; i < 2; i++ {
		if err := playlists.BuildSystemPlaylists(
			ctx, pool, logger, u.ID, time.Now().UTC(), t.TempDir(),
		); err != nil {
			t.Fatalf("build %d: %v", i, err)
		}
	}

	albums, artists := countYouMightLike(t, pool, u.ID)
	if albums > 12 {
		t.Errorf("albums = %d after two builds, want <= 12 (atomic replace)", albums)
	}
	if artists > 12 {
		t.Errorf("artists = %d after two builds, want <= 12 (atomic replace)", artists)
	}
}
