// Code generated by sqlc. DO NOT EDIT.
// versions:
//   sqlc v1.29.0
// source: idempotency-keys.sql

package sqlcv1

import (
	"context"

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

const claimIdempotencyKeys = `-- name: ClaimIdempotencyKeys :many
WITH inputs AS (
    SELECT DISTINCT
        UNNEST($1::TEXT[]) AS key,
        UNNEST($2::UUID[]) AS claimed_by_external_id
), incoming_claims AS (
    SELECT
        key, claimed_by_external_id,
        ROW_NUMBER() OVER(PARTITION BY key ORDER BY claimed_by_external_id) AS claim_index
    FROM inputs
), candidate_keys AS (
    -- Grab all of the keys that are attempting to be claimed
    SELECT
        tenant_id,
        expires_at,
        key,
        ROW_NUMBER() OVER(PARTITION BY tenant_id, key ORDER BY expires_at) AS key_index
    FROM v1_idempotency_key
    WHERE
        tenant_id = $3::UUID
        AND key IN (
            SELECT key
            FROM incoming_claims
        )
        AND claimed_by_external_id IS NULL
        AND expires_at > NOW()
), to_update AS (
    SELECT
        ck.tenant_id,
        ck.expires_at,
        ck.key,
        ic.claimed_by_external_id
    FROM candidate_keys ck
    JOIN incoming_claims ic ON (ck.key, ck.key_index) = (ic.key, ic.claim_index)
    WHERE ck.tenant_id = $3::UUID
    FOR UPDATE SKIP LOCKED
), claims AS (
    UPDATE v1_idempotency_key k
    SET
        claimed_by_external_id = u.claimed_by_external_id,
        updated_at = NOW()
    FROM to_update u
    WHERE (u.tenant_id, u.expires_at, u.key) = (k.tenant_id, k.expires_at, k.key)
    RETURNING k.tenant_id, k.key, k.expires_at, k.claimed_by_external_id, k.inserted_at, k.updated_at
)

SELECT
    i.key::TEXT AS key,
    c.expires_at::TIMESTAMPTZ AS expires_at,
    c.claimed_by_external_id IS NOT NULL::BOOLEAN AS was_successfully_claimed,
    c.claimed_by_external_id
FROM inputs i
LEFT JOIN claims c ON (i.key = c.key AND i.claimed_by_external_id = c.claimed_by_external_id)
`

type ClaimIdempotencyKeysParams struct {
	Keys                 []string    `json:"keys"`
	Claimedbyexternalids []uuid.UUID `json:"claimedbyexternalids"`
	Tenantid             uuid.UUID   `json:"tenantid"`
}

type ClaimIdempotencyKeysRow struct {
	Key                    string             `json:"key"`
	ExpiresAt              pgtype.Timestamptz `json:"expires_at"`
	WasSuccessfullyClaimed bool               `json:"was_successfully_claimed"`
	ClaimedByExternalID    *uuid.UUID         `json:"claimed_by_external_id"`
}

func (q *Queries) ClaimIdempotencyKeys(ctx context.Context, db DBTX, arg ClaimIdempotencyKeysParams) ([]*ClaimIdempotencyKeysRow, error) {
	rows, err := db.Query(ctx, claimIdempotencyKeys, arg.Keys, arg.Claimedbyexternalids, arg.Tenantid)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []*ClaimIdempotencyKeysRow
	for rows.Next() {
		var i ClaimIdempotencyKeysRow
		if err := rows.Scan(
			&i.Key,
			&i.ExpiresAt,
			&i.WasSuccessfullyClaimed,
			&i.ClaimedByExternalID,
		); err != nil {
			return nil, err
		}
		items = append(items, &i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const cleanUpExpiredIdempotencyKeys = `-- name: CleanUpExpiredIdempotencyKeys :exec
DELETE FROM v1_idempotency_key
WHERE
    tenant_id = $1::UUID
    AND expires_at < NOW()
`

func (q *Queries) CleanUpExpiredIdempotencyKeys(ctx context.Context, db DBTX, tenantid uuid.UUID) error {
	_, err := db.Exec(ctx, cleanUpExpiredIdempotencyKeys, tenantid)
	return err
}

const createIdempotencyKey = `-- name: CreateIdempotencyKey :exec
INSERT INTO v1_idempotency_key (
    tenant_id,
    key,
    expires_at
)
VALUES (
    $1::UUID,
    $2::TEXT,
    $3::TIMESTAMPTZ
)
`

type CreateIdempotencyKeyParams struct {
	Tenantid  uuid.UUID          `json:"tenantid"`
	Key       string             `json:"key"`
	Expiresat pgtype.Timestamptz `json:"expiresat"`
}

func (q *Queries) CreateIdempotencyKey(ctx context.Context, db DBTX, arg CreateIdempotencyKeyParams) error {
	_, err := db.Exec(ctx, createIdempotencyKey, arg.Tenantid, arg.Key, arg.Expiresat)
	return err
}
