// Code generated by sqlc. DO NOT EDIT.
// versions:
//   sqlc v1.31.1
// source: you_might_like.sql

package dbq

import (
	"context"

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

const countListeningSignalForUser = `-- name: CountListeningSignalForUser :one

SELECT
    count(DISTINCT pe.track_id)::bigint AS distinct_tracks,
    count(DISTINCT t.artist_id)::bigint AS distinct_artists
FROM play_events pe
JOIN tracks t ON t.id = pe.track_id
WHERE pe.user_id = $1 AND pe.was_skipped = false
`

type CountListeningSignalForUserRow struct {
	DistinctTracks  int64
	DistinctArtists int64
}

// "You might like" Home rows (#790). The daily build computes ranked
// album/artist IDs in Go (similarity roll-up + cold-start gate) and
// atomic-replaces them here; /api/home reads them back hydrated.
// Cold-start gate. Returns the breadth of the user's real listening:
// distinct unskipped tracks played and distinct artists played. The
// build skips You-might-like entirely below a threshold (a thin history
// yields near-random roll-ups). was_skipped=false so a user spamming
// next can't inflate the signal.
func (q *Queries) CountListeningSignalForUser(ctx context.Context, userID pgtype.UUID) (CountListeningSignalForUserRow, error) {
	row := q.db.QueryRow(ctx, countListeningSignalForUser, userID)
	var i CountListeningSignalForUserRow
	err := row.Scan(&i.DistinctTracks, &i.DistinctArtists)
	return i, err
}

const deleteYouMightLikeAlbumsForUser = `-- name: DeleteYouMightLikeAlbumsForUser :exec
DELETE FROM you_might_like_albums WHERE user_id = $1
`

func (q *Queries) DeleteYouMightLikeAlbumsForUser(ctx context.Context, userID pgtype.UUID) error {
	_, err := q.db.Exec(ctx, deleteYouMightLikeAlbumsForUser, userID)
	return err
}

const deleteYouMightLikeArtistsForUser = `-- name: DeleteYouMightLikeArtistsForUser :exec
DELETE FROM you_might_like_artists WHERE user_id = $1
`

func (q *Queries) DeleteYouMightLikeArtistsForUser(ctx context.Context, userID pgtype.UUID) error {
	_, err := q.db.Exec(ctx, deleteYouMightLikeArtistsForUser, userID)
	return err
}

const insertYouMightLikeAlbum = `-- name: InsertYouMightLikeAlbum :exec
INSERT INTO you_might_like_albums (user_id, album_id, rank)
VALUES ($1, $2, $3)
`

type InsertYouMightLikeAlbumParams struct {
	UserID  pgtype.UUID
	AlbumID pgtype.UUID
	Rank    int32
}

func (q *Queries) InsertYouMightLikeAlbum(ctx context.Context, arg InsertYouMightLikeAlbumParams) error {
	_, err := q.db.Exec(ctx, insertYouMightLikeAlbum, arg.UserID, arg.AlbumID, arg.Rank)
	return err
}

const insertYouMightLikeArtist = `-- name: InsertYouMightLikeArtist :exec
INSERT INTO you_might_like_artists (user_id, artist_id, rank)
VALUES ($1, $2, $3)
`

type InsertYouMightLikeArtistParams struct {
	UserID   pgtype.UUID
	ArtistID pgtype.UUID
	Rank     int32
}

func (q *Queries) InsertYouMightLikeArtist(ctx context.Context, arg InsertYouMightLikeArtistParams) error {
	_, err := q.db.Exec(ctx, insertYouMightLikeArtist, arg.UserID, arg.ArtistID, arg.Rank)
	return err
}

const listYouMightLikeAlbumFallbackForUser = `-- name: ListYouMightLikeAlbumFallbackForUser :many
WITH liked_album_ids AS (
    SELECT likb.album_id AS album_id
      FROM general_likes_albums likb
     WHERE likb.user_id = $1
    UNION
    SELECT trk.album_id AS album_id
      FROM general_likes likt
      JOIN tracks trk ON trk.id = likt.track_id
     WHERE likt.user_id = $1
)
SELECT albums.id, albums.title, albums.sort_title, albums.artist_id, albums.release_date, albums.mbid, albums.cover_art_path, albums.created_at, albums.updated_at, albums.cover_art_source, albums.cover_art_sources_version, artists.name AS artist_name
FROM liked_album_ids lai
JOIN albums ON albums.id = lai.album_id
JOIN artists ON artists.id = albums.artist_id
ORDER BY md5(albums.id::text || current_date::text)
LIMIT $2
`

type ListYouMightLikeAlbumFallbackForUserParams struct {
	UserID pgtype.UUID
	Limit  int32
}

type ListYouMightLikeAlbumFallbackForUserRow struct {
	Album      Album
	ArtistName string
}

// Broad "albums you've shown affinity for" pool: explicitly liked albums PLUS
// the albums of liked tracks. Same projection as ListYouMightLikeAlbumsForUser.
func (q *Queries) ListYouMightLikeAlbumFallbackForUser(ctx context.Context, arg ListYouMightLikeAlbumFallbackForUserParams) ([]ListYouMightLikeAlbumFallbackForUserRow, error) {
	rows, err := q.db.Query(ctx, listYouMightLikeAlbumFallbackForUser, arg.UserID, arg.Limit)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []ListYouMightLikeAlbumFallbackForUserRow
	for rows.Next() {
		var i ListYouMightLikeAlbumFallbackForUserRow
		if err := rows.Scan(
			&i.Album.ID,
			&i.Album.Title,
			&i.Album.SortTitle,
			&i.Album.ArtistID,
			&i.Album.ReleaseDate,
			&i.Album.Mbid,
			&i.Album.CoverArtPath,
			&i.Album.CreatedAt,
			&i.Album.UpdatedAt,
			&i.Album.CoverArtSource,
			&i.Album.CoverArtSourcesVersion,
			&i.ArtistName,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const listYouMightLikeAlbumsForUser = `-- name: ListYouMightLikeAlbumsForUser :many
SELECT albums.id, albums.title, albums.sort_title, albums.artist_id, albums.release_date, albums.mbid, albums.cover_art_path, albums.created_at, albums.updated_at, albums.cover_art_source, albums.cover_art_sources_version, artists.name AS artist_name
FROM you_might_like_albums yml
JOIN albums  ON albums.id  = yml.album_id
JOIN artists ON artists.id = albums.artist_id
WHERE yml.user_id = $1
ORDER BY yml.rank
LIMIT $2
`

type ListYouMightLikeAlbumsForUserParams struct {
	UserID pgtype.UUID
	Limit  int32
}

type ListYouMightLikeAlbumsForUserRow struct {
	Album      Album
	ArtistName string
}

// Read path. Same projection as ListRediscoverAlbumsForUser so the API
// layer reuses albumRefFrom(row.Album, row.ArtistName, …). Ordered by
// the rank persisted at build time. Final cross-section dedup (vs Most
// Played / Rediscover) and the output cap land in the Go layer
// (internal/recommendation/home.go).
func (q *Queries) ListYouMightLikeAlbumsForUser(ctx context.Context, arg ListYouMightLikeAlbumsForUserParams) ([]ListYouMightLikeAlbumsForUserRow, error) {
	rows, err := q.db.Query(ctx, listYouMightLikeAlbumsForUser, arg.UserID, arg.Limit)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []ListYouMightLikeAlbumsForUserRow
	for rows.Next() {
		var i ListYouMightLikeAlbumsForUserRow
		if err := rows.Scan(
			&i.Album.ID,
			&i.Album.Title,
			&i.Album.SortTitle,
			&i.Album.ArtistID,
			&i.Album.ReleaseDate,
			&i.Album.Mbid,
			&i.Album.CoverArtPath,
			&i.Album.CreatedAt,
			&i.Album.UpdatedAt,
			&i.Album.CoverArtSource,
			&i.Album.CoverArtSourcesVersion,
			&i.ArtistName,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const listYouMightLikeArtistFallbackForUser = `-- name: ListYouMightLikeArtistFallbackForUser :many
WITH liked_artist_ids AS (
    SELECT lika.artist_id AS artist_id
      FROM general_likes_artists lika
     WHERE lika.user_id = $1
    UNION
    SELECT alb.artist_id AS artist_id
      FROM general_likes_albums likb
      JOIN albums alb ON alb.id = likb.album_id
     WHERE likb.user_id = $1
    UNION
    SELECT trk.artist_id AS artist_id
      FROM general_likes likt
      JOIN tracks trk ON trk.id = likt.track_id
     WHERE likt.user_id = $1
)
SELECT artists.id, artists.name, artists.sort_name, artists.mbid, artists.created_at, artists.updated_at, artists.artist_thumb_path, artists.artist_fanart_path, artists.artist_art_source, artists.artist_art_sources_version,
       cov.id AS cover_album_id,
       cnt.album_count::bigint AS album_count
FROM liked_artist_ids lai
JOIN artists ON artists.id = lai.artist_id
LEFT JOIN LATERAL (
    SELECT id FROM albums
    WHERE artist_id = artists.id AND cover_art_path IS NOT NULL
    ORDER BY created_at DESC LIMIT 1
) cov ON true
LEFT JOIN LATERAL (
    SELECT count(*) AS album_count
    FROM albums WHERE artist_id = artists.id
) cnt ON true
ORDER BY md5(artists.id::text || current_date::text)
LIMIT $2
`

type ListYouMightLikeArtistFallbackForUserParams struct {
	UserID pgtype.UUID
	Limit  int32
}

type ListYouMightLikeArtistFallbackForUserRow struct {
	Artist       Artist
	CoverAlbumID pgtype.UUID
	AlbumCount   int64
}

// Broad "artists you've shown affinity for" pool to fill a thin
// You-might-like artists row: explicitly liked artists PLUS the artists of
// liked albums and liked tracks. Most users like albums/tracks far more than
// they like artists explicitly, so the union is much deeper than
// general_likes_artists alone. Daily-stable order; same projection as
// ListYouMightLikeArtistsForUser so the Go layer reuses it directly.
func (q *Queries) ListYouMightLikeArtistFallbackForUser(ctx context.Context, arg ListYouMightLikeArtistFallbackForUserParams) ([]ListYouMightLikeArtistFallbackForUserRow, error) {
	rows, err := q.db.Query(ctx, listYouMightLikeArtistFallbackForUser, arg.UserID, arg.Limit)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []ListYouMightLikeArtistFallbackForUserRow
	for rows.Next() {
		var i ListYouMightLikeArtistFallbackForUserRow
		if err := rows.Scan(
			&i.Artist.ID,
			&i.Artist.Name,
			&i.Artist.SortName,
			&i.Artist.Mbid,
			&i.Artist.CreatedAt,
			&i.Artist.UpdatedAt,
			&i.Artist.ArtistThumbPath,
			&i.Artist.ArtistFanartPath,
			&i.Artist.ArtistArtSource,
			&i.Artist.ArtistArtSourcesVersion,
			&i.CoverAlbumID,
			&i.AlbumCount,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const listYouMightLikeArtistsForUser = `-- name: ListYouMightLikeArtistsForUser :many
SELECT artists.id, artists.name, artists.sort_name, artists.mbid, artists.created_at, artists.updated_at, artists.artist_thumb_path, artists.artist_fanart_path, artists.artist_art_source, artists.artist_art_sources_version,
       cov.id AS cover_album_id,
       cnt.album_count::bigint AS album_count
FROM you_might_like_artists yml
JOIN artists ON artists.id = yml.artist_id
LEFT JOIN LATERAL (
    SELECT id FROM albums
    WHERE artist_id = artists.id AND cover_art_path IS NOT NULL
    ORDER BY created_at DESC LIMIT 1
) cov ON true
LEFT JOIN LATERAL (
    SELECT count(*) AS album_count
    FROM albums WHERE artist_id = artists.id
) cnt ON true
WHERE yml.user_id = $1
ORDER BY yml.rank
LIMIT $2
`

type ListYouMightLikeArtistsForUserParams struct {
	UserID pgtype.UUID
	Limit  int32
}

type ListYouMightLikeArtistsForUserRow struct {
	Artist       Artist
	CoverAlbumID pgtype.UUID
	AlbumCount   int64
}

// Read path. Same projection as ListRediscoverArtistsForUser (embeds the
// artist + a representative cover_album_id + album_count) so the API
// layer reuses artistRefFromCovered. Ordered by persisted rank.
func (q *Queries) ListYouMightLikeArtistsForUser(ctx context.Context, arg ListYouMightLikeArtistsForUserParams) ([]ListYouMightLikeArtistsForUserRow, error) {
	rows, err := q.db.Query(ctx, listYouMightLikeArtistsForUser, arg.UserID, arg.Limit)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []ListYouMightLikeArtistsForUserRow
	for rows.Next() {
		var i ListYouMightLikeArtistsForUserRow
		if err := rows.Scan(
			&i.Artist.ID,
			&i.Artist.Name,
			&i.Artist.SortName,
			&i.Artist.Mbid,
			&i.Artist.CreatedAt,
			&i.Artist.UpdatedAt,
			&i.Artist.ArtistThumbPath,
			&i.Artist.ArtistFanartPath,
			&i.Artist.ArtistArtSource,
			&i.Artist.ArtistArtSourcesVersion,
			&i.CoverAlbumID,
			&i.AlbumCount,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}
