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

package sqlcgen

import (
	"context"
	"strings"
)

const deleteAllGenres = `-- name: DeleteAllGenres :exec
DELETE FROM genres
`

func (q *Queries) DeleteAllGenres(ctx context.Context) error {
	_, err := q.db.ExecContext(ctx, deleteAllGenres)
	return err
}

const deleteFileGenres = `-- name: DeleteFileGenres :exec
DELETE FROM file_genres WHERE audio_file_id = ?
`

func (q *Queries) DeleteFileGenres(ctx context.Context, audioFileID int64) error {
	_, err := q.db.ExecContext(ctx, deleteFileGenres, audioFileID)
	return err
}

const deleteGenre = `-- name: DeleteGenre :exec
DELETE FROM genres WHERE id = ?
`

func (q *Queries) DeleteGenre(ctx context.Context, id int64) error {
	_, err := q.db.ExecContext(ctx, deleteGenre, id)
	return err
}

const getAllGenresWithCounts = `-- name: GetAllGenresWithCounts :many
SELECT g.name, COUNT(fg.audio_file_id) AS track_count
FROM genres g
JOIN file_genres fg ON fg.genre_id = g.id
JOIN audio_files af ON af.id = fg.audio_file_id
WHERE af.library_id = COALESCE(NULLIF(CAST(?1 AS INTEGER), 0), af.library_id)
GROUP BY g.id, g.name
ORDER BY g.name
`

type GetAllGenresWithCountsRow struct {
	Name       string
	TrackCount int64
}

func (q *Queries) GetAllGenresWithCounts(ctx context.Context, libraryID int64) ([]GetAllGenresWithCountsRow, error) {
	rows, err := q.db.QueryContext(ctx, getAllGenresWithCounts, libraryID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []GetAllGenresWithCountsRow
	for rows.Next() {
		var i GetAllGenresWithCountsRow
		if err := rows.Scan(&i.Name, &i.TrackCount); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Close(); err != nil {
		return nil, err
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const getGenreNamesByFile = `-- name: GetGenreNamesByFile :many
SELECT g.name FROM genres g
JOIN file_genres fg ON fg.genre_id = g.id
WHERE fg.audio_file_id = ?
`

func (q *Queries) GetGenreNamesByFile(ctx context.Context, audioFileID int64) ([]string, error) {
	rows, err := q.db.QueryContext(ctx, getGenreNamesByFile, audioFileID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []string
	for rows.Next() {
		var name string
		if err := rows.Scan(&name); err != nil {
			return nil, err
		}
		items = append(items, name)
	}
	if err := rows.Close(); err != nil {
		return nil, err
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const getGenreNamesByFilePaths = `-- name: GetGenreNamesByFilePaths :many
SELECT af.file_path, g.name
FROM audio_files af
JOIN file_genres fg ON fg.audio_file_id = af.id
JOIN genres g ON g.id = fg.genre_id
WHERE af.file_path IN (/*SLICE:paths*/?)
`

type GetGenreNamesByFilePathsRow struct {
	FilePath string
	Name     string
}

// Genres for many files at once.  The mix builder asked this one file
// at a time, inside two nested loops -- twelve thousand single-row
// queries to assemble one mix.
func (q *Queries) GetGenreNamesByFilePaths(ctx context.Context, paths []string) ([]GetGenreNamesByFilePathsRow, error) {
	query := getGenreNamesByFilePaths
	var queryParams []interface{}
	if len(paths) > 0 {
		for _, v := range paths {
			queryParams = append(queryParams, v)
		}
		query = strings.Replace(query, "/*SLICE:paths*/?", strings.Repeat(",?", len(paths))[1:], 1)
	} else {
		query = strings.Replace(query, "/*SLICE:paths*/?", "NULL", 1)
	}
	rows, err := q.db.QueryContext(ctx, query, queryParams...)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []GetGenreNamesByFilePathsRow
	for rows.Next() {
		var i GetGenreNamesByFilePathsRow
		if err := rows.Scan(&i.FilePath, &i.Name); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Close(); err != nil {
		return nil, err
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const getUnusedGenreIDs = `-- name: GetUnusedGenreIDs :many
SELECT id FROM genres g
WHERE NOT EXISTS (SELECT 1 FROM file_genres fg WHERE fg.genre_id = g.id)
`

func (q *Queries) GetUnusedGenreIDs(ctx context.Context) ([]int64, error) {
	rows, err := q.db.QueryContext(ctx, getUnusedGenreIDs)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []int64
	for rows.Next() {
		var id int64
		if err := rows.Scan(&id); err != nil {
			return nil, err
		}
		items = append(items, id)
	}
	if err := rows.Close(); err != nil {
		return nil, err
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const linkFileGenre = `-- name: LinkFileGenre :exec
INSERT OR IGNORE INTO file_genres (audio_file_id, genre_id) VALUES (?, ?)
`

type LinkFileGenreParams struct {
	AudioFileID int64
	GenreID     int64
}

func (q *Queries) LinkFileGenre(ctx context.Context, arg LinkFileGenreParams) error {
	_, err := q.db.ExecContext(ctx, linkFileGenre, arg.AudioFileID, arg.GenreID)
	return err
}

const upsertGenre = `-- name: UpsertGenre :one

INSERT INTO genres (name) VALUES (?)
ON CONFLICT(name) DO UPDATE SET name = excluded.name
RETURNING id, name
`

// Queries over genres and file_genres.
//
// The track-returning ones live in audio_files.sql with the rest of the
// track_metadata reads; what is left here is the genre list itself and
// the link table's writes.
func (q *Queries) UpsertGenre(ctx context.Context, name string) (Genre, error) {
	row := q.db.QueryRowContext(ctx, upsertGenre, name)
	var i Genre
	err := row.Scan(&i.ID, &i.Name)
	return i, err
}
