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

package db

import (
	"context"

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

const createPersonalAccessToken = `-- name: CreatePersonalAccessToken :one
INSERT INTO personal_access_token (user_id, name, token_hash, token_prefix, expires_at)
VALUES ($1, $2, $3, $4, $5)
RETURNING id, user_id, name, token_hash, token_prefix, expires_at, last_used_at, revoked, created_at
`

type CreatePersonalAccessTokenParams struct {
	UserID      pgtype.UUID        `json:"user_id"`
	Name        string             `json:"name"`
	TokenHash   string             `json:"token_hash"`
	TokenPrefix string             `json:"token_prefix"`
	ExpiresAt   pgtype.Timestamptz `json:"expires_at"`
}

func (q *Queries) CreatePersonalAccessToken(ctx context.Context, arg CreatePersonalAccessTokenParams) (PersonalAccessToken, error) {
	row := q.db.QueryRow(ctx, createPersonalAccessToken,
		arg.UserID,
		arg.Name,
		arg.TokenHash,
		arg.TokenPrefix,
		arg.ExpiresAt,
	)
	var i PersonalAccessToken
	err := row.Scan(
		&i.ID,
		&i.UserID,
		&i.Name,
		&i.TokenHash,
		&i.TokenPrefix,
		&i.ExpiresAt,
		&i.LastUsedAt,
		&i.Revoked,
		&i.CreatedAt,
	)
	return i, err
}

const extendPersonalAccessTokenExpiry = `-- name: ExtendPersonalAccessTokenExpiry :one
UPDATE personal_access_token
SET expires_at = $1
WHERE id = $2
  AND revoked = FALSE
  AND expires_at IS NOT NULL
  AND expires_at > now()
  AND expires_at <= $3
RETURNING expires_at
`

type ExtendPersonalAccessTokenExpiryParams struct {
	NewExpiresAt     pgtype.Timestamptz `json:"new_expires_at"`
	ID               pgtype.UUID        `json:"id"`
	RenewThresholdAt pgtype.Timestamptz `json:"renew_threshold_at"`
}

// In-place renew: only bumps expires_at when the token is still valid
// (not revoked, not already expired) AND the existing expires_at is
// still inside the renewal threshold ($3, e.g. now + 7d). Phrasing the
// CAS this way — "is the row still renewable?" rather than "is the
// requested new expiry larger than the current one?" — makes concurrent
// renews idempotent: once writer A bumps expires_at past the threshold,
// writer B's UPDATE matches zero rows (sqlc :one returns pgx.ErrNoRows,
// which the caller treats as "already renewed"). A naive `expires_at <
// $2` would still match because two callers race-computing
// `$2 = now + 90d` produce strictly-different values and the second
// one's $2 is always greater than the row A just wrote.
func (q *Queries) ExtendPersonalAccessTokenExpiry(ctx context.Context, arg ExtendPersonalAccessTokenExpiryParams) (pgtype.Timestamptz, error) {
	row := q.db.QueryRow(ctx, extendPersonalAccessTokenExpiry, arg.NewExpiresAt, arg.ID, arg.RenewThresholdAt)
	var expires_at pgtype.Timestamptz
	err := row.Scan(&expires_at)
	return expires_at, err
}

const getPersonalAccessTokenByHash = `-- name: GetPersonalAccessTokenByHash :one
SELECT id, user_id, name, token_hash, token_prefix, expires_at, last_used_at, revoked, created_at FROM personal_access_token
WHERE token_hash = $1
  AND revoked = FALSE
  AND (expires_at IS NULL OR expires_at > now())
`

func (q *Queries) GetPersonalAccessTokenByHash(ctx context.Context, tokenHash string) (PersonalAccessToken, error) {
	row := q.db.QueryRow(ctx, getPersonalAccessTokenByHash, tokenHash)
	var i PersonalAccessToken
	err := row.Scan(
		&i.ID,
		&i.UserID,
		&i.Name,
		&i.TokenHash,
		&i.TokenPrefix,
		&i.ExpiresAt,
		&i.LastUsedAt,
		&i.Revoked,
		&i.CreatedAt,
	)
	return i, err
}

const listPersonalAccessTokensByUser = `-- name: ListPersonalAccessTokensByUser :many
SELECT id, user_id, name, token_hash, token_prefix, expires_at, last_used_at, revoked, created_at FROM personal_access_token
WHERE user_id = $1
  AND revoked = FALSE
ORDER BY created_at DESC
`

func (q *Queries) ListPersonalAccessTokensByUser(ctx context.Context, userID pgtype.UUID) ([]PersonalAccessToken, error) {
	rows, err := q.db.Query(ctx, listPersonalAccessTokensByUser, userID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	items := []PersonalAccessToken{}
	for rows.Next() {
		var i PersonalAccessToken
		if err := rows.Scan(
			&i.ID,
			&i.UserID,
			&i.Name,
			&i.TokenHash,
			&i.TokenPrefix,
			&i.ExpiresAt,
			&i.LastUsedAt,
			&i.Revoked,
			&i.CreatedAt,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const revokePersonalAccessToken = `-- name: RevokePersonalAccessToken :one
UPDATE personal_access_token
SET revoked = TRUE
WHERE id = $1 AND user_id = $2
RETURNING token_hash
`

type RevokePersonalAccessTokenParams struct {
	ID     pgtype.UUID `json:"id"`
	UserID pgtype.UUID `json:"user_id"`
}

func (q *Queries) RevokePersonalAccessToken(ctx context.Context, arg RevokePersonalAccessTokenParams) (string, error) {
	row := q.db.QueryRow(ctx, revokePersonalAccessToken, arg.ID, arg.UserID)
	var token_hash string
	err := row.Scan(&token_hash)
	return token_hash, err
}

const updatePersonalAccessTokenLastUsed = `-- name: UpdatePersonalAccessTokenLastUsed :exec
UPDATE personal_access_token
SET last_used_at = now()
WHERE id = $1
`

func (q *Queries) UpdatePersonalAccessTokenLastUsed(ctx context.Context, id pgtype.UUID) error {
	_, err := q.db.Exec(ctx, updatePersonalAccessTokenLastUsed, id)
	return err
}
