// Code generated by sqlc. DO NOT EDIT.
// versions:
//   sqlc v1.30.0
// source: release.sql

package repository

import (
	"context"
	"time"

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

const associateArtistToRelease = `-- name: AssociateArtistToRelease :exec
INSERT INTO artist_releases (artist_id, release_id, is_primary)
VALUES ($1, $2, $3)
ON CONFLICT DO NOTHING
`

type AssociateArtistToReleaseParams struct {
	ArtistID  int32
	ReleaseID int32
	IsPrimary bool
}

func (q *Queries) AssociateArtistToRelease(ctx context.Context, arg AssociateArtistToReleaseParams) error {
	_, err := q.db.Exec(ctx, associateArtistToRelease, arg.ArtistID, arg.ReleaseID, arg.IsPrimary)
	return err
}

const countNewReleases = `-- name: CountNewReleases :one
SELECT COUNT(*) AS total_count
FROM (
  SELECT t.release_id
  FROM listens l
  JOIN tracks t ON l.track_id = t.id
  GROUP BY t.release_id
  HAVING MIN(l.listened_at) BETWEEN $1 AND $2
) first_appearances
`

type CountNewReleasesParams struct {
	ListenedAt   time.Time
	ListenedAt_2 time.Time
}

func (q *Queries) CountNewReleases(ctx context.Context, arg CountNewReleasesParams) (int64, error) {
	row := q.db.QueryRow(ctx, countNewReleases, arg.ListenedAt, arg.ListenedAt_2)
	var total_count int64
	err := row.Scan(&total_count)
	return total_count, err
}

const countReleasesFromArtist = `-- name: CountReleasesFromArtist :one
SELECT COUNT(*)
FROM releases r
JOIN artist_releases ar ON r.id = ar.release_id
WHERE ar.artist_id = $1
`

func (q *Queries) CountReleasesFromArtist(ctx context.Context, artistID int32) (int64, error) {
	row := q.db.QueryRow(ctx, countReleasesFromArtist, artistID)
	var count int64
	err := row.Scan(&count)
	return count, err
}

const countTopReleases = `-- name: CountTopReleases :one
SELECT COUNT(DISTINCT r.id) AS total_count
FROM listens l
JOIN tracks t ON l.track_id = t.id
JOIN releases r ON t.release_id = r.id
WHERE l.listened_at BETWEEN $1 AND $2
`

type CountTopReleasesParams struct {
	ListenedAt   time.Time
	ListenedAt_2 time.Time
}

func (q *Queries) CountTopReleases(ctx context.Context, arg CountTopReleasesParams) (int64, error) {
	row := q.db.QueryRow(ctx, countTopReleases, arg.ListenedAt, arg.ListenedAt_2)
	var total_count int64
	err := row.Scan(&total_count)
	return total_count, err
}

const deleteRelease = `-- name: DeleteRelease :exec
DELETE FROM releases WHERE id = $1
`

func (q *Queries) DeleteRelease(ctx context.Context, id int32) error {
	_, err := q.db.Exec(ctx, deleteRelease, id)
	return err
}

const deleteReleasesFromArtist = `-- name: DeleteReleasesFromArtist :exec
DELETE FROM releases r
USING artist_releases ar
WHERE ar.release_id = r.id
  AND ar.artist_id = $1
`

func (q *Queries) DeleteReleasesFromArtist(ctx context.Context, artistID int32) error {
	_, err := q.db.Exec(ctx, deleteReleasesFromArtist, artistID)
	return err
}

const getRelease = `-- name: GetRelease :one
SELECT
  id, musicbrainz_id, image, various_artists, image_source, title,
  get_artists_for_release(id) AS artists
FROM releases_with_title
WHERE id = $1 LIMIT 1
`

type GetReleaseRow struct {
	ID             int32
	MusicBrainzID  *uuid.UUID
	Image          *uuid.UUID
	VariousArtists bool
	ImageSource    pgtype.Text
	Title          string
	Artists        []byte
}

func (q *Queries) GetRelease(ctx context.Context, id int32) (GetReleaseRow, error) {
	row := q.db.QueryRow(ctx, getRelease, id)
	var i GetReleaseRow
	err := row.Scan(
		&i.ID,
		&i.MusicBrainzID,
		&i.Image,
		&i.VariousArtists,
		&i.ImageSource,
		&i.Title,
		&i.Artists,
	)
	return i, err
}

const getReleaseAllTimeRank = `-- name: GetReleaseAllTimeRank :one
SELECT
    release_id,
    rank
FROM (
    SELECT
        x.release_id,
        RANK() OVER (ORDER BY x.listen_count DESC) AS rank
    FROM (
        SELECT
            t.release_id,
            COUNT(*) AS listen_count
        FROM listens l
        JOIN tracks t ON l.track_id = t.id
        GROUP BY t.release_id
        ) x
    )
WHERE release_id = $1
`

type GetReleaseAllTimeRankRow struct {
	ReleaseID int32
	Rank      int64
}

func (q *Queries) GetReleaseAllTimeRank(ctx context.Context, releaseID int32) (GetReleaseAllTimeRankRow, error) {
	row := q.db.QueryRow(ctx, getReleaseAllTimeRank, releaseID)
	var i GetReleaseAllTimeRankRow
	err := row.Scan(&i.ReleaseID, &i.Rank)
	return i, err
}

const getReleaseByArtistAndTitle = `-- name: GetReleaseByArtistAndTitle :one
SELECT r.id, r.musicbrainz_id, r.image, r.various_artists, r.image_source, r.title
FROM releases_with_title r
JOIN artist_releases ar ON r.id = ar.release_id
WHERE r.title = $1 AND ar.artist_id = $2
LIMIT 1
`

type GetReleaseByArtistAndTitleParams struct {
	Title    string
	ArtistID int32
}

func (q *Queries) GetReleaseByArtistAndTitle(ctx context.Context, arg GetReleaseByArtistAndTitleParams) (ReleasesWithTitle, error) {
	row := q.db.QueryRow(ctx, getReleaseByArtistAndTitle, arg.Title, arg.ArtistID)
	var i ReleasesWithTitle
	err := row.Scan(
		&i.ID,
		&i.MusicBrainzID,
		&i.Image,
		&i.VariousArtists,
		&i.ImageSource,
		&i.Title,
	)
	return i, err
}

const getReleaseByArtistAndTitles = `-- name: GetReleaseByArtistAndTitles :one
SELECT r.id, r.musicbrainz_id, r.image, r.various_artists, r.image_source, r.title
FROM releases_with_title r
JOIN artist_releases ar ON r.id = ar.release_id
WHERE r.title = ANY ($1::TEXT[]) AND ar.artist_id = $2
LIMIT 1
`

type GetReleaseByArtistAndTitlesParams struct {
	Column1  []string
	ArtistID int32
}

func (q *Queries) GetReleaseByArtistAndTitles(ctx context.Context, arg GetReleaseByArtistAndTitlesParams) (ReleasesWithTitle, error) {
	row := q.db.QueryRow(ctx, getReleaseByArtistAndTitles, arg.Column1, arg.ArtistID)
	var i ReleasesWithTitle
	err := row.Scan(
		&i.ID,
		&i.MusicBrainzID,
		&i.Image,
		&i.VariousArtists,
		&i.ImageSource,
		&i.Title,
	)
	return i, err
}

const getReleaseByArtistAndTitlesNoMbzID = `-- name: GetReleaseByArtistAndTitlesNoMbzID :one
SELECT r.id, r.musicbrainz_id, r.image, r.various_artists, r.image_source, r.title
FROM releases_with_title r
JOIN artist_releases ar ON r.id = ar.release_id
WHERE r.title = ANY ($1::TEXT[])
  AND ar.artist_id = $2
  AND EXISTS (
    SELECT 1
    FROM releases r2
    WHERE r2.id = r.id
      AND r2.musicbrainz_id IS NULL
  )
`

type GetReleaseByArtistAndTitlesNoMbzIDParams struct {
	Column1  []string
	ArtistID int32
}

func (q *Queries) GetReleaseByArtistAndTitlesNoMbzID(ctx context.Context, arg GetReleaseByArtistAndTitlesNoMbzIDParams) (ReleasesWithTitle, error) {
	row := q.db.QueryRow(ctx, getReleaseByArtistAndTitlesNoMbzID, arg.Column1, arg.ArtistID)
	var i ReleasesWithTitle
	err := row.Scan(
		&i.ID,
		&i.MusicBrainzID,
		&i.Image,
		&i.VariousArtists,
		&i.ImageSource,
		&i.Title,
	)
	return i, err
}

const getReleaseByImageID = `-- name: GetReleaseByImageID :one
SELECT id, musicbrainz_id, image, various_artists, image_source FROM releases
WHERE image = $1 LIMIT 1
`

func (q *Queries) GetReleaseByImageID(ctx context.Context, image *uuid.UUID) (Release, error) {
	row := q.db.QueryRow(ctx, getReleaseByImageID, image)
	var i Release
	err := row.Scan(
		&i.ID,
		&i.MusicBrainzID,
		&i.Image,
		&i.VariousArtists,
		&i.ImageSource,
	)
	return i, err
}

const getReleaseByMbzID = `-- name: GetReleaseByMbzID :one
SELECT id, musicbrainz_id, image, various_artists, image_source, title FROM releases_with_title
WHERE musicbrainz_id = $1 LIMIT 1
`

func (q *Queries) GetReleaseByMbzID(ctx context.Context, musicbrainzID *uuid.UUID) (ReleasesWithTitle, error) {
	row := q.db.QueryRow(ctx, getReleaseByMbzID, musicbrainzID)
	var i ReleasesWithTitle
	err := row.Scan(
		&i.ID,
		&i.MusicBrainzID,
		&i.Image,
		&i.VariousArtists,
		&i.ImageSource,
		&i.Title,
	)
	return i, err
}

const getReleasesWithoutImages = `-- name: GetReleasesWithoutImages :many
SELECT
  r.id, r.musicbrainz_id, r.image, r.various_artists, r.image_source, r.title,
  get_artists_for_release(r.id) AS artists
FROM releases_with_title r
WHERE r.image IS NULL
  AND r.id > $2
ORDER BY r.id ASC
LIMIT $1
`

type GetReleasesWithoutImagesParams struct {
	Limit int32
	ID    int32
}

type GetReleasesWithoutImagesRow struct {
	ID             int32
	MusicBrainzID  *uuid.UUID
	Image          *uuid.UUID
	VariousArtists bool
	ImageSource    pgtype.Text
	Title          string
	Artists        []byte
}

func (q *Queries) GetReleasesWithoutImages(ctx context.Context, arg GetReleasesWithoutImagesParams) ([]GetReleasesWithoutImagesRow, error) {
	rows, err := q.db.Query(ctx, getReleasesWithoutImages, arg.Limit, arg.ID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []GetReleasesWithoutImagesRow
	for rows.Next() {
		var i GetReleasesWithoutImagesRow
		if err := rows.Scan(
			&i.ID,
			&i.MusicBrainzID,
			&i.Image,
			&i.VariousArtists,
			&i.ImageSource,
			&i.Title,
			&i.Artists,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const getTopReleasesFromArtist = `-- name: GetTopReleasesFromArtist :many
SELECT
  x.id, x.musicbrainz_id, x.image, x.various_artists, x.image_source, x.title, x.listen_count, x.artists,
  RANK() OVER (ORDER BY x.listen_count DESC) AS rank
FROM (
    SELECT
        r.id, r.musicbrainz_id, r.image, r.various_artists, r.image_source, r.title,
        COUNT(*) AS listen_count,
        get_artists_for_release(r.id) AS artists
    FROM listens l
    JOIN tracks t ON l.track_id = t.id
    JOIN releases_with_title r ON t.release_id = r.id
    JOIN artist_releases ar ON r.id = ar.release_id
    WHERE ar.artist_id = $5
    AND l.listened_at BETWEEN $1 AND $2
    GROUP BY r.id, r.title, r.musicbrainz_id, r.various_artists, r.image, r.image_source
) x
ORDER BY listen_count DESC, x.id
LIMIT $3 OFFSET $4
`

type GetTopReleasesFromArtistParams struct {
	ListenedAt   time.Time
	ListenedAt_2 time.Time
	Limit        int32
	Offset       int32
	ArtistID     int32
}

type GetTopReleasesFromArtistRow struct {
	ID             int32
	MusicBrainzID  *uuid.UUID
	Image          *uuid.UUID
	VariousArtists bool
	ImageSource    pgtype.Text
	Title          string
	ListenCount    int64
	Artists        []byte
	Rank           int64
}

func (q *Queries) GetTopReleasesFromArtist(ctx context.Context, arg GetTopReleasesFromArtistParams) ([]GetTopReleasesFromArtistRow, error) {
	rows, err := q.db.Query(ctx, getTopReleasesFromArtist,
		arg.ListenedAt,
		arg.ListenedAt_2,
		arg.Limit,
		arg.Offset,
		arg.ArtistID,
	)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []GetTopReleasesFromArtistRow
	for rows.Next() {
		var i GetTopReleasesFromArtistRow
		if err := rows.Scan(
			&i.ID,
			&i.MusicBrainzID,
			&i.Image,
			&i.VariousArtists,
			&i.ImageSource,
			&i.Title,
			&i.ListenCount,
			&i.Artists,
			&i.Rank,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const getTopReleasesPaginated = `-- name: GetTopReleasesPaginated :many
SELECT
  x.id, x.musicbrainz_id, x.image, x.various_artists, x.image_source, x.title, x.listen_count, x.artists,
  RANK() OVER (ORDER BY x.listen_count DESC) AS rank
FROM (
    SELECT
        r.id, r.musicbrainz_id, r.image, r.various_artists, r.image_source, r.title,
        COUNT(*) AS listen_count,
        get_artists_for_release(r.id) AS artists
    FROM listens l
    JOIN tracks t ON l.track_id = t.id
    JOIN releases_with_title r ON t.release_id = r.id
    WHERE l.listened_at BETWEEN $1 AND $2
    GROUP BY r.id, r.title, r.musicbrainz_id, r.various_artists, r.image, r.image_source
) x
ORDER BY listen_count DESC, x.id
LIMIT $3 OFFSET $4
`

type GetTopReleasesPaginatedParams struct {
	ListenedAt   time.Time
	ListenedAt_2 time.Time
	Limit        int32
	Offset       int32
}

type GetTopReleasesPaginatedRow struct {
	ID             int32
	MusicBrainzID  *uuid.UUID
	Image          *uuid.UUID
	VariousArtists bool
	ImageSource    pgtype.Text
	Title          string
	ListenCount    int64
	Artists        []byte
	Rank           int64
}

func (q *Queries) GetTopReleasesPaginated(ctx context.Context, arg GetTopReleasesPaginatedParams) ([]GetTopReleasesPaginatedRow, error) {
	rows, err := q.db.Query(ctx, getTopReleasesPaginated,
		arg.ListenedAt,
		arg.ListenedAt_2,
		arg.Limit,
		arg.Offset,
	)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []GetTopReleasesPaginatedRow
	for rows.Next() {
		var i GetTopReleasesPaginatedRow
		if err := rows.Scan(
			&i.ID,
			&i.MusicBrainzID,
			&i.Image,
			&i.VariousArtists,
			&i.ImageSource,
			&i.Title,
			&i.ListenCount,
			&i.Artists,
			&i.Rank,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const insertRelease = `-- name: InsertRelease :one
INSERT INTO releases (musicbrainz_id, various_artists, image, image_source)
VALUES ($1, $2, $3, $4)
RETURNING id, musicbrainz_id, image, various_artists, image_source
`

type InsertReleaseParams struct {
	MusicBrainzID  *uuid.UUID
	VariousArtists bool
	Image          *uuid.UUID
	ImageSource    pgtype.Text
}

func (q *Queries) InsertRelease(ctx context.Context, arg InsertReleaseParams) (Release, error) {
	row := q.db.QueryRow(ctx, insertRelease,
		arg.MusicBrainzID,
		arg.VariousArtists,
		arg.Image,
		arg.ImageSource,
	)
	var i Release
	err := row.Scan(
		&i.ID,
		&i.MusicBrainzID,
		&i.Image,
		&i.VariousArtists,
		&i.ImageSource,
	)
	return i, err
}

const updateReleaseImage = `-- name: UpdateReleaseImage :exec
UPDATE releases SET image = $2, image_source = $3
WHERE id = $1
`

type UpdateReleaseImageParams struct {
	ID          int32
	Image       *uuid.UUID
	ImageSource pgtype.Text
}

func (q *Queries) UpdateReleaseImage(ctx context.Context, arg UpdateReleaseImageParams) error {
	_, err := q.db.Exec(ctx, updateReleaseImage, arg.ID, arg.Image, arg.ImageSource)
	return err
}

const updateReleaseMbzID = `-- name: UpdateReleaseMbzID :exec
UPDATE releases SET musicbrainz_id = $2
WHERE id = $1
`

type UpdateReleaseMbzIDParams struct {
	ID            int32
	MusicBrainzID *uuid.UUID
}

func (q *Queries) UpdateReleaseMbzID(ctx context.Context, arg UpdateReleaseMbzIDParams) error {
	_, err := q.db.Exec(ctx, updateReleaseMbzID, arg.ID, arg.MusicBrainzID)
	return err
}

const updateReleasePrimaryArtist = `-- name: UpdateReleasePrimaryArtist :exec
UPDATE artist_releases SET is_primary = $3
WHERE artist_id = $1 AND release_id = $2
`

type UpdateReleasePrimaryArtistParams struct {
	ArtistID  int32
	ReleaseID int32
	IsPrimary bool
}

func (q *Queries) UpdateReleasePrimaryArtist(ctx context.Context, arg UpdateReleasePrimaryArtistParams) error {
	_, err := q.db.Exec(ctx, updateReleasePrimaryArtist, arg.ArtistID, arg.ReleaseID, arg.IsPrimary)
	return err
}

const updateReleaseVariousArtists = `-- name: UpdateReleaseVariousArtists :exec
UPDATE releases SET various_artists = $2
WHERE id = $1
`

type UpdateReleaseVariousArtistsParams struct {
	ID             int32
	VariousArtists bool
}

func (q *Queries) UpdateReleaseVariousArtists(ctx context.Context, arg UpdateReleaseVariousArtistsParams) error {
	_, err := q.db.Exec(ctx, updateReleaseVariousArtists, arg.ID, arg.VariousArtists)
	return err
}
