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

package dbq

import (
	"context"

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

const countQuarantineForTrack = `-- name: CountQuarantineForTrack :one
SELECT count(*)::int FROM lidarr_quarantine WHERE track_id = $1
`

// Reads affected_users for the audit row before the delete fires.
func (q *Queries) CountQuarantineForTrack(ctx context.Context, trackID pgtype.UUID) (int32, error) {
	row := q.db.QueryRow(ctx, countQuarantineForTrack, trackID)
	var column_1 int32
	err := row.Scan(&column_1)
	return column_1, err
}

const deleteQuarantine = `-- name: DeleteQuarantine :one
DELETE FROM lidarr_quarantine
 WHERE user_id = $1 AND track_id = $2
 RETURNING user_id, track_id, reason, notes, created_at
`

type DeleteQuarantineParams struct {
	UserID  pgtype.UUID
	TrackID pgtype.UUID
}

// Removes the caller's row. Returns the deleted row so the handler can
// distinguish "no row existed" (zero rows -> ErrNoRows) from success.
func (q *Queries) DeleteQuarantine(ctx context.Context, arg DeleteQuarantineParams) (LidarrQuarantine, error) {
	row := q.db.QueryRow(ctx, deleteQuarantine, arg.UserID, arg.TrackID)
	var i LidarrQuarantine
	err := row.Scan(
		&i.UserID,
		&i.TrackID,
		&i.Reason,
		&i.Notes,
		&i.CreatedAt,
	)
	return i, err
}

const deleteQuarantineForTrack = `-- name: DeleteQuarantineForTrack :exec
DELETE FROM lidarr_quarantine WHERE track_id = $1
`

// Clears all per-user rows for a given track. Used by Resolve and the
// two delete actions. Caller writes the audit row separately before
// this fires (so we can capture the affected_users count).
func (q *Queries) DeleteQuarantineForTrack(ctx context.Context, trackID pgtype.UUID) error {
	_, err := q.db.Exec(ctx, deleteQuarantineForTrack, trackID)
	return err
}

const listAdminQuarantineQueue = `-- name: ListAdminQuarantineQueue :many
SELECT
    t.id              AS track_id,
    t.title           AS track_title,
    ar.name           AS artist_name,
    al.title          AS album_title,
    al.id             AS album_id,
    al.mbid           AS lidarr_album_mbid,
    count(q.user_id)::int             AS report_count,
    max(q.created_at)::timestamptz    AS latest_at
FROM lidarr_quarantine q
JOIN tracks  t  ON t.id  = q.track_id
JOIN albums  al ON al.id = t.album_id
JOIN artists ar ON ar.id = t.artist_id
GROUP BY t.id, ar.name, al.title, al.id, al.mbid
ORDER BY max(q.created_at) DESC
`

type ListAdminQuarantineQueueRow struct {
	TrackID         pgtype.UUID
	TrackTitle      string
	ArtistName      string
	AlbumTitle      string
	AlbumID         pgtype.UUID
	LidarrAlbumMbid *string
	ReportCount     int32
	LatestAt        pgtype.Timestamptz
}

// Aggregated admin queue. One row per track. The handler post-processes
// the rows it gets from this query plus a per-track ListQuarantineReports
// call to materialize reason_counts and the per-user reports list.
func (q *Queries) ListAdminQuarantineQueue(ctx context.Context) ([]ListAdminQuarantineQueueRow, error) {
	rows, err := q.db.Query(ctx, listAdminQuarantineQueue)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []ListAdminQuarantineQueueRow
	for rows.Next() {
		var i ListAdminQuarantineQueueRow
		if err := rows.Scan(
			&i.TrackID,
			&i.TrackTitle,
			&i.ArtistName,
			&i.AlbumTitle,
			&i.AlbumID,
			&i.LidarrAlbumMbid,
			&i.ReportCount,
			&i.LatestAt,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const listQuarantineActions = `-- name: ListQuarantineActions :many
SELECT id, track_id, track_title, artist_name, album_title, action, admin_id, lidarr_album_mbid, affected_users, created_at FROM lidarr_quarantine_actions
ORDER BY created_at DESC
LIMIT $1
`

func (q *Queries) ListQuarantineActions(ctx context.Context, limit int32) ([]LidarrQuarantineAction, error) {
	rows, err := q.db.Query(ctx, listQuarantineActions, limit)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []LidarrQuarantineAction
	for rows.Next() {
		var i LidarrQuarantineAction
		if err := rows.Scan(
			&i.ID,
			&i.TrackID,
			&i.TrackTitle,
			&i.ArtistName,
			&i.AlbumTitle,
			&i.Action,
			&i.AdminID,
			&i.LidarrAlbumMbid,
			&i.AffectedUsers,
			&i.CreatedAt,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const listQuarantineForUser = `-- name: ListQuarantineForUser :many
SELECT
    q.user_id, q.track_id, q.reason, q.notes, q.created_at,
    t.id          AS track_id_join,
    t.title       AS track_title,
    t.duration_ms AS track_duration_ms,
    al.id         AS album_id,
    al.title      AS album_title,
    al.cover_art_path AS album_cover_art_path,
    ar.id         AS artist_id,
    ar.name       AS artist_name
FROM lidarr_quarantine q
JOIN tracks  t  ON t.id  = q.track_id
JOIN albums  al ON al.id = t.album_id
JOIN artists ar ON ar.id = t.artist_id
WHERE q.user_id = $1
ORDER BY q.created_at DESC
`

type ListQuarantineForUserRow struct {
	LidarrQuarantine  LidarrQuarantine
	TrackIDJoin       pgtype.UUID
	TrackTitle        string
	TrackDurationMs   int32
	AlbumID           pgtype.UUID
	AlbumTitle        string
	AlbumCoverArtPath *string
	ArtistID          pgtype.UUID
	ArtistName        string
}

// Caller's own quarantines plus just the joined fields the SPA's
// /library/hidden actually renders. Embedding the full tracks/albums/artists
// structs would drag ~28 columns of file_path / sort_* / mbid / etc. that
// the row card never uses.
func (q *Queries) ListQuarantineForUser(ctx context.Context, userID pgtype.UUID) ([]ListQuarantineForUserRow, error) {
	rows, err := q.db.Query(ctx, listQuarantineForUser, userID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []ListQuarantineForUserRow
	for rows.Next() {
		var i ListQuarantineForUserRow
		if err := rows.Scan(
			&i.LidarrQuarantine.UserID,
			&i.LidarrQuarantine.TrackID,
			&i.LidarrQuarantine.Reason,
			&i.LidarrQuarantine.Notes,
			&i.LidarrQuarantine.CreatedAt,
			&i.TrackIDJoin,
			&i.TrackTitle,
			&i.TrackDurationMs,
			&i.AlbumID,
			&i.AlbumTitle,
			&i.AlbumCoverArtPath,
			&i.ArtistID,
			&i.ArtistName,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const listQuarantineReportsForTrack = `-- name: ListQuarantineReportsForTrack :many
SELECT
    q.user_id,
    u.username,
    q.reason,
    q.notes,
    q.created_at
FROM lidarr_quarantine q
JOIN users u ON u.id = q.user_id
WHERE q.track_id = $1
ORDER BY q.created_at DESC
`

type ListQuarantineReportsForTrackRow struct {
	UserID    pgtype.UUID
	Username  string
	Reason    LidarrQuarantineReason
	Notes     *string
	CreatedAt pgtype.Timestamptz
}

// Per-user reports for a single track. Returned by ListAdminQuarantineQueue
// post-processing and exposed expandable in the SPA admin queue rows.
func (q *Queries) ListQuarantineReportsForTrack(ctx context.Context, trackID pgtype.UUID) ([]ListQuarantineReportsForTrackRow, error) {
	rows, err := q.db.Query(ctx, listQuarantineReportsForTrack, trackID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []ListQuarantineReportsForTrackRow
	for rows.Next() {
		var i ListQuarantineReportsForTrackRow
		if err := rows.Scan(
			&i.UserID,
			&i.Username,
			&i.Reason,
			&i.Notes,
			&i.CreatedAt,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const upsertQuarantine = `-- name: UpsertQuarantine :one
INSERT INTO lidarr_quarantine (user_id, track_id, reason, notes)
VALUES ($1, $2, $3, $4)
ON CONFLICT (user_id, track_id) DO UPDATE SET
    reason     = EXCLUDED.reason,
    notes      = EXCLUDED.notes,
    created_at = now()
RETURNING user_id, track_id, reason, notes, created_at
`

type UpsertQuarantineParams struct {
	UserID  pgtype.UUID
	TrackID pgtype.UUID
	Reason  LidarrQuarantineReason
	Notes   *string
}

// Insert a new quarantine row, or update reason/notes if the user has
// already flagged this track.
func (q *Queries) UpsertQuarantine(ctx context.Context, arg UpsertQuarantineParams) (LidarrQuarantine, error) {
	row := q.db.QueryRow(ctx, upsertQuarantine,
		arg.UserID,
		arg.TrackID,
		arg.Reason,
		arg.Notes,
	)
	var i LidarrQuarantine
	err := row.Scan(
		&i.UserID,
		&i.TrackID,
		&i.Reason,
		&i.Notes,
		&i.CreatedAt,
	)
	return i, err
}

const writeQuarantineAction = `-- name: WriteQuarantineAction :one
INSERT INTO lidarr_quarantine_actions (
    track_id, track_title, artist_name, album_title,
    action, admin_id, lidarr_album_mbid, affected_users
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
RETURNING id, track_id, track_title, artist_name, album_title, action, admin_id, lidarr_album_mbid, affected_users, created_at
`

type WriteQuarantineActionParams struct {
	TrackID         pgtype.UUID
	TrackTitle      string
	ArtistName      string
	AlbumTitle      *string
	Action          LidarrQuarantineActionKind
	AdminID         pgtype.UUID
	LidarrAlbumMbid *string
	AffectedUsers   int32
}

// Audit row for an admin destructive action.
func (q *Queries) WriteQuarantineAction(ctx context.Context, arg WriteQuarantineActionParams) (LidarrQuarantineAction, error) {
	row := q.db.QueryRow(ctx, writeQuarantineAction,
		arg.TrackID,
		arg.TrackTitle,
		arg.ArtistName,
		arg.AlbumTitle,
		arg.Action,
		arg.AdminID,
		arg.LidarrAlbumMbid,
		arg.AffectedUsers,
	)
	var i LidarrQuarantineAction
	err := row.Scan(
		&i.ID,
		&i.TrackID,
		&i.TrackTitle,
		&i.ArtistName,
		&i.AlbumTitle,
		&i.Action,
		&i.AdminID,
		&i.LidarrAlbumMbid,
		&i.AffectedUsers,
		&i.CreatedAt,
	)
	return i, err
}
