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

package repository

import (
	"context"
	"time"

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

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

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

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

const countTopArtists = `-- name: CountTopArtists :one
SELECT COUNT(DISTINCT at.artist_id) AS total_count
FROM listens l
JOIN artist_tracks at ON l.track_id = at.track_id
WHERE l.listened_at BETWEEN $1 AND $2
`

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

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

const deleteArtist = `-- name: DeleteArtist :exec
DELETE FROM artists WHERE id = $1
`

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

const deleteConflictingArtistReleases = `-- name: DeleteConflictingArtistReleases :exec
DELETE FROM artist_releases ar
WHERE ar.artist_id = $1
  AND release_id IN (
    SELECT ar.release_id FROM artist_releases ar WHERE ar.artist_id = $2
  )
`

type DeleteConflictingArtistReleasesParams struct {
	ArtistID   int32
	ArtistID_2 int32
}

func (q *Queries) DeleteConflictingArtistReleases(ctx context.Context, arg DeleteConflictingArtistReleasesParams) error {
	_, err := q.db.Exec(ctx, deleteConflictingArtistReleases, arg.ArtistID, arg.ArtistID_2)
	return err
}

const deleteConflictingArtistTracks = `-- name: DeleteConflictingArtistTracks :exec
DELETE FROM artist_tracks at
WHERE at.artist_id = $1
  AND track_id IN (
    SELECT at.track_id FROM artist_tracks at WHERE at.artist_id = $2
  )
`

type DeleteConflictingArtistTracksParams struct {
	ArtistID   int32
	ArtistID_2 int32
}

func (q *Queries) DeleteConflictingArtistTracks(ctx context.Context, arg DeleteConflictingArtistTracksParams) error {
	_, err := q.db.Exec(ctx, deleteConflictingArtistTracks, arg.ArtistID, arg.ArtistID_2)
	return err
}

const getArtist = `-- name: GetArtist :one
SELECT
  a.id, a.musicbrainz_id, a.image, a.image_source, a.name,
  array_agg(aa.alias)::text[] AS aliases
FROM artists_with_name a
LEFT JOIN artist_aliases aa ON a.id = aa.artist_id
WHERE a.id = $1
GROUP BY a.id, a.musicbrainz_id, a.image, a.image_source, a.name
`

type GetArtistRow struct {
	ID            int32
	MusicBrainzID *uuid.UUID
	Image         *uuid.UUID
	ImageSource   pgtype.Text
	Name          string
	Aliases       []string
}

func (q *Queries) GetArtist(ctx context.Context, id int32) (GetArtistRow, error) {
	row := q.db.QueryRow(ctx, getArtist, id)
	var i GetArtistRow
	err := row.Scan(
		&i.ID,
		&i.MusicBrainzID,
		&i.Image,
		&i.ImageSource,
		&i.Name,
		&i.Aliases,
	)
	return i, err
}

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

type GetArtistAllTimeRankRow struct {
	ArtistID int32
	Rank     int64
}

func (q *Queries) GetArtistAllTimeRank(ctx context.Context, artistID int32) (GetArtistAllTimeRankRow, error) {
	row := q.db.QueryRow(ctx, getArtistAllTimeRank, artistID)
	var i GetArtistAllTimeRankRow
	err := row.Scan(&i.ArtistID, &i.Rank)
	return i, err
}

const getArtistByImage = `-- name: GetArtistByImage :one
SELECT id, musicbrainz_id, image, image_source FROM artists WHERE image = $1 LIMIT 1
`

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

const getArtistByMbzID = `-- name: GetArtistByMbzID :one
SELECT
  a.id, a.musicbrainz_id, a.image, a.image_source, a.name,
  array_agg(aa.alias)::text[] AS aliases
FROM artists_with_name a
LEFT JOIN artist_aliases aa ON a.id = aa.artist_id
WHERE a.musicbrainz_id = $1
GROUP BY a.id, a.musicbrainz_id, a.image, a.image_source, a.name
`

type GetArtistByMbzIDRow struct {
	ID            int32
	MusicBrainzID *uuid.UUID
	Image         *uuid.UUID
	ImageSource   pgtype.Text
	Name          string
	Aliases       []string
}

func (q *Queries) GetArtistByMbzID(ctx context.Context, musicbrainzID *uuid.UUID) (GetArtistByMbzIDRow, error) {
	row := q.db.QueryRow(ctx, getArtistByMbzID, musicbrainzID)
	var i GetArtistByMbzIDRow
	err := row.Scan(
		&i.ID,
		&i.MusicBrainzID,
		&i.Image,
		&i.ImageSource,
		&i.Name,
		&i.Aliases,
	)
	return i, err
}

const getArtistByName = `-- name: GetArtistByName :one
WITH artist_with_aliases AS (
  SELECT
    a.id, a.musicbrainz_id, a.image, a.image_source, a.name,
    COALESCE(array_agg(aa.alias), '{}')::text[] AS aliases
  FROM artists_with_name a
  LEFT JOIN artist_aliases aa ON a.id = aa.artist_id
  WHERE a.id IN (
    SELECT aa2.artist_id FROM artist_aliases aa2 WHERE aa2.alias = $1
  )
  GROUP BY a.id, a.musicbrainz_id, a.image, a.image_source, a.name
)
SELECT id, musicbrainz_id, image, image_source, name, aliases FROM artist_with_aliases
`

type GetArtistByNameRow struct {
	ID            int32
	MusicBrainzID *uuid.UUID
	Image         *uuid.UUID
	ImageSource   pgtype.Text
	Name          string
	Aliases       []string
}

func (q *Queries) GetArtistByName(ctx context.Context, alias string) (GetArtistByNameRow, error) {
	row := q.db.QueryRow(ctx, getArtistByName, alias)
	var i GetArtistByNameRow
	err := row.Scan(
		&i.ID,
		&i.MusicBrainzID,
		&i.Image,
		&i.ImageSource,
		&i.Name,
		&i.Aliases,
	)
	return i, err
}

const getArtistsWithoutImages = `-- name: GetArtistsWithoutImages :many
SELECT
    id, musicbrainz_id, image, image_source, name
FROM artists_with_name
WHERE image IS NULL
  AND id > $2
ORDER BY id ASC
LIMIT $1
`

type GetArtistsWithoutImagesParams struct {
	Limit int32
	ID    int32
}

func (q *Queries) GetArtistsWithoutImages(ctx context.Context, arg GetArtistsWithoutImagesParams) ([]ArtistsWithName, error) {
	rows, err := q.db.Query(ctx, getArtistsWithoutImages, arg.Limit, arg.ID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []ArtistsWithName
	for rows.Next() {
		var i ArtistsWithName
		if err := rows.Scan(
			&i.ID,
			&i.MusicBrainzID,
			&i.Image,
			&i.ImageSource,
			&i.Name,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const getReleaseArtists = `-- name: GetReleaseArtists :many
SELECT
  a.id, a.musicbrainz_id, a.image, a.image_source, a.name,
  ar.is_primary as is_primary
FROM artists_with_name a
LEFT JOIN artist_releases ar ON a.id = ar.artist_id
WHERE ar.release_id = $1
GROUP BY a.id, a.musicbrainz_id, a.image, a.image_source, a.name, ar.is_primary
`

type GetReleaseArtistsRow struct {
	ID            int32
	MusicBrainzID *uuid.UUID
	Image         *uuid.UUID
	ImageSource   pgtype.Text
	Name          string
	IsPrimary     pgtype.Bool
}

func (q *Queries) GetReleaseArtists(ctx context.Context, releaseID int32) ([]GetReleaseArtistsRow, error) {
	rows, err := q.db.Query(ctx, getReleaseArtists, releaseID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []GetReleaseArtistsRow
	for rows.Next() {
		var i GetReleaseArtistsRow
		if err := rows.Scan(
			&i.ID,
			&i.MusicBrainzID,
			&i.Image,
			&i.ImageSource,
			&i.Name,
			&i.IsPrimary,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const getTopArtistsPaginated = `-- name: GetTopArtistsPaginated :many
SELECT
  x.id,
  x.name,
  x.musicbrainz_id,
  x.image,
  x.listen_count,
  RANK() OVER (ORDER BY x.listen_count DESC) AS rank
FROM (
  SELECT
    a.id,
    a.name,
    a.musicbrainz_id,
    a.image,
    COUNT(*) AS listen_count
  FROM listens l
  JOIN tracks t ON l.track_id = t.id
  JOIN artist_tracks at ON at.track_id = t.id
  JOIN artists_with_name a ON a.id = at.artist_id
  WHERE l.listened_at BETWEEN $1 AND $2
  GROUP BY a.id, a.name, a.musicbrainz_id, a.image
) x
ORDER BY x.listen_count DESC, x.id
LIMIT $3 OFFSET $4
`

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

type GetTopArtistsPaginatedRow struct {
	ID            int32
	Name          string
	MusicBrainzID *uuid.UUID
	Image         *uuid.UUID
	ListenCount   int64
	Rank          int64
}

func (q *Queries) GetTopArtistsPaginated(ctx context.Context, arg GetTopArtistsPaginatedParams) ([]GetTopArtistsPaginatedRow, error) {
	rows, err := q.db.Query(ctx, getTopArtistsPaginated,
		arg.ListenedAt,
		arg.ListenedAt_2,
		arg.Limit,
		arg.Offset,
	)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []GetTopArtistsPaginatedRow
	for rows.Next() {
		var i GetTopArtistsPaginatedRow
		if err := rows.Scan(
			&i.ID,
			&i.Name,
			&i.MusicBrainzID,
			&i.Image,
			&i.ListenCount,
			&i.Rank,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const getTrackArtists = `-- name: GetTrackArtists :many
SELECT
  a.id, a.musicbrainz_id, a.image, a.image_source, a.name,
  at.is_primary as is_primary
FROM artists_with_name a
LEFT JOIN artist_tracks at ON a.id = at.artist_id
WHERE at.track_id = $1
GROUP BY a.id, a.musicbrainz_id, a.image, a.image_source, a.name, at.is_primary
`

type GetTrackArtistsRow struct {
	ID            int32
	MusicBrainzID *uuid.UUID
	Image         *uuid.UUID
	ImageSource   pgtype.Text
	Name          string
	IsPrimary     pgtype.Bool
}

func (q *Queries) GetTrackArtists(ctx context.Context, trackID int32) ([]GetTrackArtistsRow, error) {
	rows, err := q.db.Query(ctx, getTrackArtists, trackID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []GetTrackArtistsRow
	for rows.Next() {
		var i GetTrackArtistsRow
		if err := rows.Scan(
			&i.ID,
			&i.MusicBrainzID,
			&i.Image,
			&i.ImageSource,
			&i.Name,
			&i.IsPrimary,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const insertArtist = `-- name: InsertArtist :one
INSERT INTO artists (musicbrainz_id, image, image_source)
VALUES ($1, $2, $3)
RETURNING id, musicbrainz_id, image, image_source
`

type InsertArtistParams struct {
	MusicBrainzID *uuid.UUID
	Image         *uuid.UUID
	ImageSource   pgtype.Text
}

func (q *Queries) InsertArtist(ctx context.Context, arg InsertArtistParams) (Artist, error) {
	row := q.db.QueryRow(ctx, insertArtist, arg.MusicBrainzID, arg.Image, arg.ImageSource)
	var i Artist
	err := row.Scan(
		&i.ID,
		&i.MusicBrainzID,
		&i.Image,
		&i.ImageSource,
	)
	return i, err
}

const updateArtistImage = `-- name: UpdateArtistImage :exec
UPDATE artists SET image = $2, image_source = $3
WHERE id = $1
`

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

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

const updateArtistMbzID = `-- name: UpdateArtistMbzID :exec
UPDATE artists SET musicbrainz_id = $2
WHERE id = $1
`

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

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

const updateArtistReleases = `-- name: UpdateArtistReleases :exec
UPDATE artist_releases
SET artist_id = $2
WHERE artist_id = $1
`

type UpdateArtistReleasesParams struct {
	ArtistID   int32
	ArtistID_2 int32
}

func (q *Queries) UpdateArtistReleases(ctx context.Context, arg UpdateArtistReleasesParams) error {
	_, err := q.db.Exec(ctx, updateArtistReleases, arg.ArtistID, arg.ArtistID_2)
	return err
}

const updateArtistTracks = `-- name: UpdateArtistTracks :exec
UPDATE artist_tracks
SET artist_id = $2
WHERE artist_id = $1
`

type UpdateArtistTracksParams struct {
	ArtistID   int32
	ArtistID_2 int32
}

func (q *Queries) UpdateArtistTracks(ctx context.Context, arg UpdateArtistTracksParams) error {
	_, err := q.db.Exec(ctx, updateArtistTracks, arg.ArtistID, arg.ArtistID_2)
	return err
}
