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

package dbq

import (
	"context"

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

const insertPlaybackError = `-- name: InsertPlaybackError :one
INSERT INTO playback_errors (track_id, user_id, client_id, kind, detail)
VALUES ($1, $2, $3, $4, $5)
RETURNING id, track_id, user_id, client_id, kind, detail, occurred_at,
          resolved_at, resolved_by, resolution
`

type InsertPlaybackErrorParams struct {
	TrackID  pgtype.UUID
	UserID   pgtype.UUID
	ClientID string
	Kind     string
	Detail   *string
}

// Records a client-reported playback failure. The handler validates
// the kind enum before this runs; the CHECK constraint is a
// belt-and-braces guard.
func (q *Queries) InsertPlaybackError(ctx context.Context, arg InsertPlaybackErrorParams) (PlaybackError, error) {
	row := q.db.QueryRow(ctx, insertPlaybackError,
		arg.TrackID,
		arg.UserID,
		arg.ClientID,
		arg.Kind,
		arg.Detail,
	)
	var i PlaybackError
	err := row.Scan(
		&i.ID,
		&i.TrackID,
		&i.UserID,
		&i.ClientID,
		&i.Kind,
		&i.Detail,
		&i.OccurredAt,
		&i.ResolvedAt,
		&i.ResolvedBy,
		&i.Resolution,
	)
	return i, err
}

const listAdminPlaybackErrors = `-- name: ListAdminPlaybackErrors :many
SELECT
    pe.id            AS id,
    pe.track_id      AS track_id,
    pe.user_id       AS user_id,
    u.username       AS username,
    pe.client_id     AS client_id,
    pe.kind          AS kind,
    pe.detail        AS detail,
    pe.occurred_at   AS occurred_at,
    pe.resolved_at   AS resolved_at,
    pe.resolution    AS resolution,
    t.title          AS track_title,
    t.file_path      AS track_file_path,
    ar.name          AS artist_name,
    al.title         AS album_title,
    al.id            AS album_id
FROM playback_errors pe
JOIN users   u  ON u.id  = pe.user_id
JOIN tracks  t  ON t.id  = pe.track_id
JOIN albums  al ON al.id = t.album_id
JOIN artists ar ON ar.id = t.artist_id
WHERE ($1::bool AND pe.resolved_at IS NOT NULL)
   OR (NOT $1::bool AND pe.resolved_at IS NULL)
ORDER BY pe.occurred_at DESC
LIMIT $3::int OFFSET $2::int
`

type ListAdminPlaybackErrorsParams struct {
	ResolvedFilter bool
	Off            int32
	Lim            int32
}

type ListAdminPlaybackErrorsRow struct {
	ID            pgtype.UUID
	TrackID       pgtype.UUID
	UserID        pgtype.UUID
	Username      string
	ClientID      string
	Kind          string
	Detail        *string
	OccurredAt    pgtype.Timestamptz
	ResolvedAt    pgtype.Timestamptz
	Resolution    *string
	TrackTitle    string
	TrackFilePath string
	ArtistName    string
	AlbumTitle    string
	AlbumID       pgtype.UUID
}

// Admin inbox query. Returns one row per playback_errors row joined
// with track / album / artist metadata so the SPA can render without
// a second round-trip. Filter by resolved status via the sqlc.arg —
// pass true for the Resolved tab, false for Unresolved (the default).
func (q *Queries) ListAdminPlaybackErrors(ctx context.Context, arg ListAdminPlaybackErrorsParams) ([]ListAdminPlaybackErrorsRow, error) {
	rows, err := q.db.Query(ctx, listAdminPlaybackErrors, arg.ResolvedFilter, arg.Off, arg.Lim)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []ListAdminPlaybackErrorsRow
	for rows.Next() {
		var i ListAdminPlaybackErrorsRow
		if err := rows.Scan(
			&i.ID,
			&i.TrackID,
			&i.UserID,
			&i.Username,
			&i.ClientID,
			&i.Kind,
			&i.Detail,
			&i.OccurredAt,
			&i.ResolvedAt,
			&i.Resolution,
			&i.TrackTitle,
			&i.TrackFilePath,
			&i.ArtistName,
			&i.AlbumTitle,
			&i.AlbumID,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const resolveAllPlaybackErrorsForTrack = `-- name: ResolveAllPlaybackErrorsForTrack :execrows
UPDATE playback_errors
   SET resolved_at = now(),
       resolved_by = $2,
       resolution  = $3
 WHERE track_id = $1 AND resolved_at IS NULL
`

type ResolveAllPlaybackErrorsForTrackParams struct {
	TrackID    pgtype.UUID
	ResolvedBy pgtype.UUID
	Resolution *string
}

// Bulk-resolve every unresolved error for a track when an admin acts
// on it from a non-inbox surface (existing quarantine flow, etc.).
// Returns the affected row count so the caller can surface "N reports
// auto-resolved" in the response if useful.
func (q *Queries) ResolveAllPlaybackErrorsForTrack(ctx context.Context, arg ResolveAllPlaybackErrorsForTrackParams) (int64, error) {
	result, err := q.db.Exec(ctx, resolveAllPlaybackErrorsForTrack, arg.TrackID, arg.ResolvedBy, arg.Resolution)
	if err != nil {
		return 0, err
	}
	return result.RowsAffected(), nil
}

const resolvePlaybackError = `-- name: ResolvePlaybackError :one
UPDATE playback_errors
   SET resolved_at = now(),
       resolved_by = $2,
       resolution  = $3
 WHERE id = $1
RETURNING id, track_id, user_id, client_id, kind, detail, occurred_at,
          resolved_at, resolved_by, resolution
`

type ResolvePlaybackErrorParams struct {
	ID         pgtype.UUID
	ResolvedBy pgtype.UUID
	Resolution *string
}

// Marks a single error resolved. Idempotent over (id, resolution) —
// a second resolve with the same resolution is a no-op rewrite. Returns
// the row so the handler can echo it. The CHECK constraint enforces
// the resolution enum.
func (q *Queries) ResolvePlaybackError(ctx context.Context, arg ResolvePlaybackErrorParams) (PlaybackError, error) {
	row := q.db.QueryRow(ctx, resolvePlaybackError, arg.ID, arg.ResolvedBy, arg.Resolution)
	var i PlaybackError
	err := row.Scan(
		&i.ID,
		&i.TrackID,
		&i.UserID,
		&i.ClientID,
		&i.Kind,
		&i.Detail,
		&i.OccurredAt,
		&i.ResolvedAt,
		&i.ResolvedBy,
		&i.Resolution,
	)
	return i, err
}
